Merge branch 'fix/misc' into for-linus
[pandora-kernel.git] / arch / mips / vr41xx / common / siu.c
1 /*
2  *  NEC VR4100 series SIU platform device.
3  *
4  *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@linux-mips.org>
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
29 static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
30         PORT_VR41XX_SIU,
31         PORT_UNKNOWN,
32 };
33
34 static 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
47 static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
48         PORT_VR41XX_SIU,
49         PORT_VR41XX_DSIU,
50 };
51
52 static 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
75 static 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_type()) {
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
115 err_free_device:
116         platform_device_put(pdev);
117
118         return retval;
119 }
120 device_initcall(vr41xx_siu_add);
121
122 void __init vr41xx_siu_setup(void)
123 {
124         struct uart_port port;
125         struct resource *res;
126         unsigned int *type;
127         int i;
128
129         switch (current_cpu_type()) {
130         case CPU_VR4111:
131         case CPU_VR4121:
132                 type = siu_type1_ports;
133                 res = siu_type1_resource;
134                 break;
135         case CPU_VR4122:
136         case CPU_VR4131:
137         case CPU_VR4133:
138                 type = siu_type2_ports;
139                 res = siu_type2_resource;
140                 break;
141         default:
142                 return;
143         }
144
145         for (i = 0; i < SIU_PORTS_MAX; i++) {
146                 port.line = i;
147                 port.type = type[i];
148                 if (port.type == PORT_UNKNOWN)
149                         break;
150                 port.mapbase = res[i].start;
151                 port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start);
152                 vr41xx_siu_early_setup(&port);
153         }
154 }