aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/vr41xx/common/Makefile2
-rw-r--r--arch/mips/vr41xx/common/siu.c120
-rw-r--r--drivers/serial/vr41xx_siu.c143
-rw-r--r--include/asm-mips/vr41xx/siu.h2
4 files changed, 153 insertions, 114 deletions
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index f842783acd86..fcf94d7b1478 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,4 +2,4 @@
2# Makefile for common code of the NEC VR4100 series. 2# Makefile for common code of the NEC VR4100 series.
3# 3#
4 4
5obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o 5obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o siu.o type.o
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
new file mode 100644
index 000000000000..a1e774142163
--- /dev/null
+++ b/arch/mips/vr41xx/common/siu.c
@@ -0,0 +1,120 @@
1/*
2 * NEC VR4100 series SIU platform device.
3 *
4 * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/ioport.h>
23#include <linux/platform_device.h>
24#include <linux/serial_core.h>
25
26#include <asm/cpu.h>
27#include <asm/vr41xx/siu.h>
28
29static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
30 PORT_VR41XX_SIU,
31 PORT_UNKNOWN,
32};
33
34static struct resource siu_type1_resource[] __initdata = {
35 {
36 .start = 0x0c000000,
37 .end = 0x0c00000a,
38 .flags = IORESOURCE_MEM,
39 },
40 {
41 .start = SIU_IRQ,
42 .end = SIU_IRQ,
43 .flags = IORESOURCE_IRQ,
44 },
45};
46
47static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
48 PORT_VR41XX_SIU,
49 PORT_VR41XX_DSIU,
50};
51
52static struct resource siu_type2_resource[] __initdata = {
53 {
54 .start = 0x0f000800,
55 .end = 0x0f00080a,
56 .flags = IORESOURCE_MEM,
57 },
58 {
59 .start = 0x0f000820,
60 .end = 0x0f000829,
61 .flags = IORESOURCE_MEM,
62 },
63 {
64 .start = SIU_IRQ,
65 .end = SIU_IRQ,
66 .flags = IORESOURCE_IRQ,
67 },
68 {
69 .start = DSIU_IRQ,
70 .end = DSIU_IRQ,
71 .flags = IORESOURCE_IRQ,
72 },
73};
74
75static int __init vr41xx_siu_add(void)
76{
77 struct platform_device *pdev;
78 struct resource *res;
79 unsigned int num;
80 int retval;
81
82 pdev = platform_device_alloc("SIU", -1);
83 if (!pdev)
84 return -ENOMEM;
85
86 switch (current_cpu_data.cputype) {
87 case CPU_VR4111:
88 case CPU_VR4121:
89 pdev->dev.platform_data = siu_type1_ports;
90 res = siu_type1_resource;
91 num = ARRAY_SIZE(siu_type1_resource);
92 break;
93 case CPU_VR4122:
94 case CPU_VR4131:
95 case CPU_VR4133:
96 pdev->dev.platform_data = siu_type2_ports;
97 res = siu_type2_resource;
98 num = ARRAY_SIZE(siu_type2_resource);
99 break;
100 default:
101 retval = -ENODEV;
102 goto err_free_device;
103 }
104
105 retval = platform_device_add_resources(pdev, res, num);
106 if (retval)
107 goto err_free_device;
108
109 retval = platform_device_add(pdev);
110 if (retval)
111 goto err_free_device;
112
113 return 0;
114
115err_free_device:
116 platform_device_put(pdev);
117
118 return retval;
119}
120device_initcall(vr41xx_siu_add);
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index cf0e663b42ed..85309acb75f6 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for NEC VR4100 series Serial Interface Unit. 2 * Driver for NEC VR4100 series Serial Interface Unit.
3 * 3 *
4 * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 4 * Copyright (C) 2004-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
5 * 5 *
6 * Based on drivers/serial/8250.c, by Russell King. 6 * Based on drivers/serial/8250.c, by Russell King.
7 * 7 *
@@ -25,12 +25,12 @@
25#endif 25#endif
26 26
27#include <linux/console.h> 27#include <linux/console.h>
28#include <linux/platform_device.h> 28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/ioport.h>
31#include <linux/init.h> 29#include <linux/init.h>
32#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/ioport.h>
33#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/platform_device.h>
34#include <linux/serial.h> 34#include <linux/serial.h>
35#include <linux/serial_core.h> 35#include <linux/serial_core.h>
36#include <linux/serial_reg.h> 36#include <linux/serial_reg.h>
@@ -38,11 +38,9 @@
38#include <linux/tty_flip.h> 38#include <linux/tty_flip.h>
39 39
40#include <asm/io.h> 40#include <asm/io.h>
41#include <asm/vr41xx/irq.h>
42#include <asm/vr41xx/siu.h> 41#include <asm/vr41xx/siu.h>
43#include <asm/vr41xx/vr41xx.h> 42#include <asm/vr41xx/vr41xx.h>
44 43
45#define SIU_PORTS_MAX 2
46#define SIU_BAUD_BASE 1152000 44#define SIU_BAUD_BASE 1152000
47#define SIU_MAJOR 204 45#define SIU_MAJOR 204
48#define SIU_MINOR_BASE 82 46#define SIU_MINOR_BASE 82
@@ -60,32 +58,13 @@
60 #define IRUSESEL 0x02 58 #define IRUSESEL 0x02
61 #define SIRSEL 0x01 59 #define SIRSEL 0x01
62 60
63struct siu_port { 61static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
64 unsigned int type; 62 [0 ... SIU_PORTS_MAX-1] = {
65 unsigned int irq; 63 .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
66 unsigned long start; 64 .irq = -1,
67}; 65 },
68
69static const struct siu_port siu_type1_ports[] = {
70 { .type = PORT_VR41XX_SIU,
71 .irq = SIU_IRQ,
72 .start = 0x0c000000UL, },
73};
74
75#define SIU_TYPE1_NR_PORTS (sizeof(siu_type1_ports) / sizeof(struct siu_port))
76
77static const struct siu_port siu_type2_ports[] = {
78 { .type = PORT_VR41XX_SIU,
79 .irq = SIU_IRQ,
80 .start = 0x0f000800UL, },
81 { .type = PORT_VR41XX_DSIU,
82 .irq = DSIU_IRQ,
83 .start = 0x0f000820UL, },
84}; 66};
85 67
86#define SIU_TYPE2_NR_PORTS (sizeof(siu_type2_ports) / sizeof(struct siu_port))
87
88static struct uart_port siu_uart_ports[SIU_PORTS_MAX];
89static uint8_t lsr_break_flag[SIU_PORTS_MAX]; 68static uint8_t lsr_break_flag[SIU_PORTS_MAX];
90 69
91#define siu_read(port, offset) readb((port)->membase + (offset)) 70#define siu_read(port, offset) readb((port)->membase + (offset))
@@ -110,7 +89,6 @@ void vr41xx_select_siu_interface(siu_interface_t interface)
110 89
111 spin_unlock_irqrestore(&port->lock, flags); 90 spin_unlock_irqrestore(&port->lock, flags);
112} 91}
113
114EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface); 92EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
115 93
116void vr41xx_use_irda(irda_use_t use) 94void vr41xx_use_irda(irda_use_t use)
@@ -132,7 +110,6 @@ void vr41xx_use_irda(irda_use_t use)
132 110
133 spin_unlock_irqrestore(&port->lock, flags); 111 spin_unlock_irqrestore(&port->lock, flags);
134} 112}
135
136EXPORT_SYMBOL_GPL(vr41xx_use_irda); 113EXPORT_SYMBOL_GPL(vr41xx_use_irda);
137 114
138void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed) 115void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
@@ -166,7 +143,6 @@ void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
166 143
167 spin_unlock_irqrestore(&port->lock, flags); 144 spin_unlock_irqrestore(&port->lock, flags);
168} 145}
169
170EXPORT_SYMBOL_GPL(vr41xx_select_irda_module); 146EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
171 147
172static inline void siu_clear_fifo(struct uart_port *port) 148static inline void siu_clear_fifo(struct uart_port *port)
@@ -177,21 +153,6 @@ static inline void siu_clear_fifo(struct uart_port *port)
177 siu_write(port, UART_FCR, 0); 153 siu_write(port, UART_FCR, 0);
178} 154}
179 155
180static inline int siu_probe_ports(void)
181{
182 switch (current_cpu_data.cputype) {
183 case CPU_VR4111:
184 case CPU_VR4121:
185 return SIU_TYPE1_NR_PORTS;
186 case CPU_VR4122:
187 case CPU_VR4131:
188 case CPU_VR4133:
189 return SIU_TYPE2_NR_PORTS;
190 }
191
192 return 0;
193}
194
195static inline unsigned long siu_port_size(struct uart_port *port) 156static inline unsigned long siu_port_size(struct uart_port *port)
196{ 157{
197 switch (port->type) { 158 switch (port->type) {
@@ -206,21 +167,10 @@ static inline unsigned long siu_port_size(struct uart_port *port)
206 167
207static inline unsigned int siu_check_type(struct uart_port *port) 168static inline unsigned int siu_check_type(struct uart_port *port)
208{ 169{
209 switch (current_cpu_data.cputype) { 170 if (port->line == 0)
210 case CPU_VR4111: 171 return PORT_VR41XX_SIU;
211 case CPU_VR4121: 172 if (port->line == 1 && port->irq != -1)
212 if (port->line == 0) 173 return PORT_VR41XX_DSIU;
213 return PORT_VR41XX_SIU;
214 break;
215 case CPU_VR4122:
216 case CPU_VR4131:
217 case CPU_VR4133:
218 if (port->line == 0)
219 return PORT_VR41XX_SIU;
220 else if (port->line == 1)
221 return PORT_VR41XX_DSIU;
222 break;
223 }
224 174
225 return PORT_UNKNOWN; 175 return PORT_UNKNOWN;
226} 176}
@@ -751,44 +701,34 @@ static struct uart_ops siu_uart_ops = {
751 .verify_port = siu_verify_port, 701 .verify_port = siu_verify_port,
752}; 702};
753 703
754static int siu_init_ports(void) 704static int siu_init_ports(struct platform_device *pdev)
755{ 705{
756 const struct siu_port *siu;
757 struct uart_port *port; 706 struct uart_port *port;
758 int i, num; 707 struct resource *res;
708 int *type = pdev->dev.platform_data;
709 int i;
759 710
760 switch (current_cpu_data.cputype) { 711 if (!type)
761 case CPU_VR4111:
762 case CPU_VR4121:
763 siu = siu_type1_ports;
764 break;
765 case CPU_VR4122:
766 case CPU_VR4131:
767 case CPU_VR4133:
768 siu = siu_type2_ports;
769 break;
770 default:
771 return 0; 712 return 0;
772 }
773 713
774 port = siu_uart_ports; 714 port = siu_uart_ports;
775 num = siu_probe_ports(); 715 for (i = 0; i < SIU_PORTS_MAX; i++) {
776 for (i = 0; i < num; i++) { 716 port->type = type[i];
777 spin_lock_init(&port->lock); 717 if (port->type == PORT_UNKNOWN)
778 port->irq = siu->irq; 718 continue;
719 port->irq = platform_get_irq(pdev, i);
779 port->uartclk = SIU_BAUD_BASE * 16; 720 port->uartclk = SIU_BAUD_BASE * 16;
780 port->fifosize = 16; 721 port->fifosize = 16;
781 port->regshift = 0; 722 port->regshift = 0;
782 port->iotype = UPIO_MEM; 723 port->iotype = UPIO_MEM;
783 port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; 724 port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
784 port->type = siu->type;
785 port->line = i; 725 port->line = i;
786 port->mapbase = siu->start; 726 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
787 siu++; 727 port->mapbase = res->start;
788 port++; 728 port++;
789 } 729 }
790 730
791 return num; 731 return i;
792} 732}
793 733
794#ifdef CONFIG_SERIAL_VR41XX_CONSOLE 734#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
@@ -883,13 +823,9 @@ static struct console siu_console = {
883static int __devinit siu_console_init(void) 823static int __devinit siu_console_init(void)
884{ 824{
885 struct uart_port *port; 825 struct uart_port *port;
886 int num, i; 826 int i;
887
888 num = siu_init_ports();
889 if (num <= 0)
890 return -ENODEV;
891 827
892 for (i = 0; i < num; i++) { 828 for (i = 0; i < SIU_PORTS_MAX; i++) {
893 port = &siu_uart_ports[i]; 829 port = &siu_uart_ports[i];
894 port->ops = &siu_uart_ops; 830 port->ops = &siu_uart_ops;
895 } 831 }
@@ -920,7 +856,7 @@ static int __devinit siu_probe(struct platform_device *dev)
920 struct uart_port *port; 856 struct uart_port *port;
921 int num, i, retval; 857 int num, i, retval;
922 858
923 num = siu_init_ports(); 859 num = siu_init_ports(dev);
924 if (num <= 0) 860 if (num <= 0)
925 return -ENODEV; 861 return -ENODEV;
926 862
@@ -998,8 +934,6 @@ static int siu_resume(struct platform_device *dev)
998 return 0; 934 return 0;
999} 935}
1000 936
1001static struct platform_device *siu_platform_device;
1002
1003static struct platform_driver siu_device_driver = { 937static struct platform_driver siu_device_driver = {
1004 .probe = siu_probe, 938 .probe = siu_probe,
1005 .remove = __devexit_p(siu_remove), 939 .remove = __devexit_p(siu_remove),
@@ -1013,29 +947,12 @@ static struct platform_driver siu_device_driver = {
1013 947
1014static int __init vr41xx_siu_init(void) 948static int __init vr41xx_siu_init(void)
1015{ 949{
1016 int retval; 950 return platform_driver_register(&siu_device_driver);
1017
1018 siu_platform_device = platform_device_alloc("SIU", -1);
1019 if (!siu_platform_device)
1020 return -ENOMEM;
1021
1022 retval = platform_device_add(siu_platform_device);
1023 if (retval < 0) {
1024 platform_device_put(siu_platform_device);
1025 return retval;
1026 }
1027
1028 retval = platform_driver_register(&siu_device_driver);
1029 if (retval < 0)
1030 platform_device_unregister(siu_platform_device);
1031
1032 return retval;
1033} 951}
1034 952
1035static void __exit vr41xx_siu_exit(void) 953static void __exit vr41xx_siu_exit(void)
1036{ 954{
1037 platform_driver_unregister(&siu_device_driver); 955 platform_driver_unregister(&siu_device_driver);
1038 platform_device_unregister(siu_platform_device);
1039} 956}
1040 957
1041module_init(vr41xx_siu_init); 958module_init(vr41xx_siu_init);
diff --git a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
index 1fcf6e8082b4..98cdb4096485 100644
--- a/include/asm-mips/vr41xx/siu.h
+++ b/include/asm-mips/vr41xx/siu.h
@@ -20,6 +20,8 @@
20#ifndef __NEC_VR41XX_SIU_H 20#ifndef __NEC_VR41XX_SIU_H
21#define __NEC_VR41XX_SIU_H 21#define __NEC_VR41XX_SIU_H
22 22
23#define SIU_PORTS_MAX 2
24
23typedef enum { 25typedef enum {
24 SIU_INTERFACE_RS232C, 26 SIU_INTERFACE_RS232C,
25 SIU_INTERFACE_IRDA, 27 SIU_INTERFACE_IRDA,