Merge branches 'release' and 'hp-cid' into release
[linux-2.6] / arch / arm / mach-orion / common.c
1 /*
2  * arch/arm/mach-orion/common.c
3  *
4  * Core functions for Marvell Orion System On Chip
5  *
6  * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7  *
8  * This file is licensed under  the terms of the GNU General Public
9  * License version 2. This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <linux/serial_8250.h>
17 #include <linux/mv643xx_eth.h>
18 #include <linux/mv643xx_i2c.h>
19 #include <asm/page.h>
20 #include <asm/timex.h>
21 #include <asm/mach/map.h>
22 #include <asm/arch/orion.h>
23 #include "common.h"
24
25 /*****************************************************************************
26  * I/O Address Mapping
27  ****************************************************************************/
28 static struct map_desc orion_io_desc[] __initdata = {
29         {
30                 .virtual        = ORION_REGS_BASE,
31                 .pfn            = __phys_to_pfn(ORION_REGS_BASE),
32                 .length         = ORION_REGS_SIZE,
33                 .type           = MT_DEVICE
34         },
35         {
36                 .virtual        = ORION_PCIE_IO_BASE,
37                 .pfn            = __phys_to_pfn(ORION_PCIE_IO_BASE),
38                 .length         = ORION_PCIE_IO_SIZE,
39                 .type           = MT_DEVICE
40         },
41         {
42                 .virtual        = ORION_PCI_IO_BASE,
43                 .pfn            = __phys_to_pfn(ORION_PCI_IO_BASE),
44                 .length         = ORION_PCI_IO_SIZE,
45                 .type           = MT_DEVICE
46         },
47         {
48                 .virtual        = ORION_PCIE_WA_BASE,
49                 .pfn            = __phys_to_pfn(ORION_PCIE_WA_BASE),
50                 .length         = ORION_PCIE_WA_SIZE,
51                 .type           = MT_DEVICE
52         },
53 };
54
55 void __init orion_map_io(void)
56 {
57         iotable_init(orion_io_desc, ARRAY_SIZE(orion_io_desc));
58 }
59
60 /*****************************************************************************
61  * UART
62  ****************************************************************************/
63
64 static struct resource orion_uart_resources[] = {
65         {
66                 .start          = UART0_BASE,
67                 .end            = UART0_BASE + 0xff,
68                 .flags          = IORESOURCE_MEM,
69         },
70         {
71                 .start          = IRQ_ORION_UART0,
72                 .end            = IRQ_ORION_UART0,
73                 .flags          = IORESOURCE_IRQ,
74         },
75         {
76                 .start          = UART1_BASE,
77                 .end            = UART1_BASE + 0xff,
78                 .flags          = IORESOURCE_MEM,
79         },
80         {
81                 .start          = IRQ_ORION_UART1,
82                 .end            = IRQ_ORION_UART1,
83                 .flags          = IORESOURCE_IRQ,
84         },
85 };
86
87 static struct plat_serial8250_port orion_uart_data[] = {
88         {
89                 .mapbase        = UART0_BASE,
90                 .membase        = (char *)UART0_BASE,
91                 .irq            = IRQ_ORION_UART0,
92                 .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
93                 .iotype         = UPIO_MEM,
94                 .regshift       = 2,
95                 .uartclk        = ORION_TCLK,
96         },
97         {
98                 .mapbase        = UART1_BASE,
99                 .membase        = (char *)UART1_BASE,
100                 .irq            = IRQ_ORION_UART1,
101                 .flags          = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
102                 .iotype         = UPIO_MEM,
103                 .regshift       = 2,
104                 .uartclk        = ORION_TCLK,
105         },
106         { },
107 };
108
109 static struct platform_device orion_uart = {
110         .name                   = "serial8250",
111         .id                     = PLAT8250_DEV_PLATFORM,
112         .dev                    = {
113                 .platform_data  = orion_uart_data,
114         },
115         .resource               = orion_uart_resources,
116         .num_resources          = ARRAY_SIZE(orion_uart_resources),
117 };
118
119 /*******************************************************************************
120  * USB Controller - 2 interfaces
121  ******************************************************************************/
122
123 static struct resource orion_ehci0_resources[] = {
124         {
125                 .start  = ORION_USB0_REG_BASE,
126                 .end    = ORION_USB0_REG_BASE + SZ_4K,
127                 .flags  = IORESOURCE_MEM,
128         },
129         {
130                 .start  = IRQ_ORION_USB0_CTRL,
131                 .end    = IRQ_ORION_USB0_CTRL,
132                 .flags  = IORESOURCE_IRQ,
133         },
134 };
135
136 static struct resource orion_ehci1_resources[] = {
137         {
138                 .start  = ORION_USB1_REG_BASE,
139                 .end    = ORION_USB1_REG_BASE + SZ_4K,
140                 .flags  = IORESOURCE_MEM,
141         },
142         {
143                 .start  = IRQ_ORION_USB1_CTRL,
144                 .end    = IRQ_ORION_USB1_CTRL,
145                 .flags  = IORESOURCE_IRQ,
146         },
147 };
148
149 static u64 ehci_dmamask = 0xffffffffUL;
150
151 static struct platform_device orion_ehci0 = {
152         .name           = "orion-ehci",
153         .id             = 0,
154         .dev            = {
155                 .dma_mask               = &ehci_dmamask,
156                 .coherent_dma_mask      = 0xffffffff,
157         },
158         .resource       = orion_ehci0_resources,
159         .num_resources  = ARRAY_SIZE(orion_ehci0_resources),
160 };
161
162 static struct platform_device orion_ehci1 = {
163         .name           = "orion-ehci",
164         .id             = 1,
165         .dev            = {
166                 .dma_mask               = &ehci_dmamask,
167                 .coherent_dma_mask      = 0xffffffff,
168         },
169         .resource       = orion_ehci1_resources,
170         .num_resources  = ARRAY_SIZE(orion_ehci1_resources),
171 };
172
173 /*****************************************************************************
174  * Gigabit Ethernet port
175  * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
176  ****************************************************************************/
177
178 static struct resource orion_eth_shared_resources[] = {
179         {
180                 .start  = ORION_ETH_REG_BASE,
181                 .end    = ORION_ETH_REG_BASE + 0xffff,
182                 .flags  = IORESOURCE_MEM,
183         },
184 };
185
186 static struct platform_device orion_eth_shared = {
187         .name           = MV643XX_ETH_SHARED_NAME,
188         .id             = 0,
189         .num_resources  = 1,
190         .resource       = orion_eth_shared_resources,
191 };
192
193 static struct resource orion_eth_resources[] = {
194         {
195                 .name   = "eth irq",
196                 .start  = IRQ_ORION_ETH_SUM,
197                 .end    = IRQ_ORION_ETH_SUM,
198                 .flags  = IORESOURCE_IRQ,
199         }
200 };
201
202 static struct platform_device orion_eth = {
203         .name           = MV643XX_ETH_NAME,
204         .id             = 0,
205         .num_resources  = 1,
206         .resource       = orion_eth_resources,
207 };
208
209 void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data)
210 {
211         orion_eth.dev.platform_data = eth_data;
212         platform_device_register(&orion_eth_shared);
213         platform_device_register(&orion_eth);
214 }
215
216 /*****************************************************************************
217  * I2C controller
218  * (The Orion and Discovery (MV643xx) families share the same I2C controller)
219  ****************************************************************************/
220
221 static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
222         .freq_m         = 8, /* assumes 166 MHz TCLK */
223         .freq_n         = 3,
224         .timeout        = 1000, /* Default timeout of 1 second */
225 };
226
227 static struct resource orion_i2c_resources[] = {
228         {
229                 .name   = "i2c base",
230                 .start  = I2C_BASE,
231                 .end    = I2C_BASE + 0x20 -1,
232                 .flags  = IORESOURCE_MEM,
233         },
234         {
235                 .name   = "i2c irq",
236                 .start  = IRQ_ORION_I2C,
237                 .end    = IRQ_ORION_I2C,
238                 .flags  = IORESOURCE_IRQ,
239         },
240 };
241
242 static struct platform_device orion_i2c = {
243         .name           = MV64XXX_I2C_CTLR_NAME,
244         .id             = 0,
245         .num_resources  = ARRAY_SIZE(orion_i2c_resources),
246         .resource       = orion_i2c_resources,
247         .dev            = {
248                 .platform_data = &orion_i2c_pdata,
249         },
250 };
251
252 /*****************************************************************************
253  * General
254  ****************************************************************************/
255
256 /*
257  * Identify device ID and rev from PCIE configuration header space '0'.
258  */
259 static void orion_id(u32 *dev, u32 *rev, char **dev_name)
260 {
261         orion_pcie_id(dev, rev);
262
263         if (*dev == MV88F5281_DEV_ID) {
264                 if (*rev == MV88F5281_REV_D2) {
265                         *dev_name = "MV88F5281-D2";
266                 } else if (*rev == MV88F5281_REV_D1) {
267                         *dev_name = "MV88F5281-D1";
268                 } else {
269                         *dev_name = "MV88F5281-Rev-Unsupported";
270                 }
271         } else if (*dev == MV88F5182_DEV_ID) {
272                 if (*rev == MV88F5182_REV_A2) {
273                         *dev_name = "MV88F5182-A2";
274                 } else {
275                         *dev_name = "MV88F5182-Rev-Unsupported";
276                 }
277         } else if (*dev == MV88F5181_DEV_ID) {
278                 if (*rev == MV88F5181_REV_B1) {
279                         *dev_name = "MV88F5181-Rev-B1";
280                 } else {
281                         *dev_name = "MV88F5181-Rev-Unsupported";
282                 }
283         } else {
284                 *dev_name = "Device-Unknown";
285         }
286 }
287
288 void __init orion_init(void)
289 {
290         char *dev_name;
291         u32 dev, rev;
292
293         orion_id(&dev, &rev, &dev_name);
294         printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION_TCLK);
295
296         /*
297          * Setup Orion address map
298          */
299         orion_setup_cpu_wins();
300         orion_setup_usb_wins();
301         orion_setup_eth_wins();
302         orion_setup_pci_wins();
303         orion_setup_pcie_wins();
304         if (dev == MV88F5182_DEV_ID)
305                 orion_setup_sata_wins();
306
307         /*
308          * REgister devices
309          */
310         platform_device_register(&orion_uart);
311         platform_device_register(&orion_ehci0);
312         if (dev == MV88F5182_DEV_ID)
313                 platform_device_register(&orion_ehci1);
314         platform_device_register(&orion_i2c);
315 }