32becc30e9dbadb72df070e70a0e5d4d410e563f
[librecmc/librecmc.git] / target / linux / cns3xxx / patches / 100-laguna_support.patch
1 --- /dev/null
2 +++ b/arch/arm/mach-cns3xxx/laguna.c
3 @@ -0,0 +1,671 @@
4 +/*
5 + * Gateworks Corporation Laguna Platform
6 + *
7 + * Copyright 2000 Deep Blue Solutions Ltd
8 + * Copyright 2008 ARM Limited
9 + * Copyright 2008 Cavium Networks
10 + *               Scott Shu
11 + * Copyright 2010 MontaVista Software, LLC.
12 + *               Anton Vorontsov <avorontsov@mvista.com>
13 + * Copyright 2011 Gateworks Corporation
14 + *               Chris Lang <clang@gateworks.com>
15 + *
16 + * This file is free software; you can redistribute it and/or modify
17 + * it under the terms of the GNU General Public License, Version 2, as
18 + * published by the Free Software Foundation.
19 + */
20 +
21 +#include <linux/init.h>
22 +#include <linux/kernel.h>
23 +#include <linux/compiler.h>
24 +#include <linux/io.h>
25 +#include <linux/dma-mapping.h>
26 +#include <linux/serial_core.h>
27 +#include <linux/serial_8250.h>
28 +#include <linux/platform_device.h>
29 +#include <linux/mtd/mtd.h>
30 +#include <linux/mtd/physmap.h>
31 +#include <linux/mtd/partitions.h>
32 +#include <linux/leds.h>
33 +#include <linux/i2c.h>
34 +#include <linux/i2c/at24.h>
35 +#include <linux/i2c/pca953x.h>
36 +#include <linux/spi/spi.h>
37 +#include <linux/spi/flash.h>
38 +#include <linux/if_ether.h>
39 +#include <asm/setup.h>
40 +#include <asm/mach-types.h>
41 +#include <asm/mach/arch.h>
42 +#include <asm/mach/map.h>
43 +#include <asm/mach/time.h>
44 +#include <mach/hardware.h>
45 +#include <mach/cns3xxx.h>
46 +#include <mach/irqs.h>
47 +#include <mach/pm.h>
48 +#include "core.h"
49 +#include "devices.h"
50 +
51 +// Config 1 Bitmap
52 +#define ETH0_LOAD           BIT(0)
53 +#define ETH1_LOAD           BIT(1)
54 +#define ETH2_LOAD           BIT(2)
55 +#define SATA0_LOAD          BIT(3)
56 +#define SATA1_LOAD          BIT(4)
57 +#define PCM_LOAD            BIT(5)
58 +#define I2S_LOAD            BIT(6)
59 +#define SPI0_LOAD           BIT(7)
60 +#define SPI1_LOAD           BIT(8)
61 +#define PCIE0_LOAD          BIT(9)
62 +#define PCIE1_LOAD          BIT(10)
63 +#define USB0_LOAD           BIT(11)
64 +#define USB1_LOAD           BIT(12)
65 +#define USB1_ROUTE          BIT(13)
66 +#define SD_LOAD             BIT(14)
67 +#define UART0_LOAD          BIT(15)
68 +#define UART1_LOAD          BIT(16)
69 +#define UART2_LOAD          BIT(17)
70 +#define MPCI0_LOAD          BIT(18)
71 +#define MPCI1_LOAD          BIT(19)
72 +#define MPCI2_LOAD          BIT(20)
73 +#define MPCI3_LOAD          BIT(21)
74 +#define FP_BUT_LOAD         BIT(22)
75 +#define FP_BUT_HEADER_LOAD  BIT(23)
76 +#define FP_LED_LOAD         BIT(24)
77 +#define FP_LED_HEADER_LOAD  BIT(25)
78 +#define FP_TAMPER_LOAD      BIT(26)
79 +#define HEADER_33V_LOAD     BIT(27)
80 +#define SATA_POWER_LOAD     BIT(28)
81 +#define FP_POWER_LOAD       BIT(29)
82 +#define GPIO_HEADER_LOAD    BIT(30)
83 +#define GSP_BAT_LOAD        BIT(31)
84 +
85 +// Config 2 Bitmap
86 +#define FAN_LOAD            BIT(0)
87 +#define SPI_FLASH_LOAD      BIT(1)
88 +#define NOR_FLASH_LOAD      BIT(2)
89 +#define GPS_LOAD            BIT(3)
90 +#define SUPPLY_5V_LOAD      BIT(6)
91 +#define SUPPLY_33V_LOAD     BIT(7)
92 +
93 +struct laguna_board_info {
94 +       char model[16];
95 +       u32 config_bitmap;
96 +       u32 config2_bitmap;
97 +       u8 nor_flash_size;
98 +       u8 spi_flash_size;
99 +};
100 +
101 +static struct laguna_board_info laguna_info __initdata;
102 +
103 +/*
104 + * NOR Flash
105 + */
106 +static struct mtd_partition laguna_nor_partitions[] = {
107 +       {
108 +               .name           = "uboot",
109 +               .size           = SZ_256K,
110 +               .offset         = 0,
111 +               .mask_flags     = MTD_WRITEABLE,
112 +       }, {
113 +               .name           = "params",
114 +               .size           = SZ_128K,
115 +               .offset         = SZ_256K,
116 +       }, {
117 +               .name           = "kernel",
118 +               .size           = SZ_2M,
119 +               .offset         = SZ_256K + SZ_128K,
120 +       }, {
121 +               .name           = "rootfs",
122 +               .size           = SZ_16M - SZ_256K - SZ_128K - SZ_2M,
123 +               .offset         = SZ_256K + SZ_128K + SZ_2M,
124 +       },
125 +};
126 +
127 +static struct physmap_flash_data laguna_nor_pdata = {
128 +       .width = 2,
129 +       .parts = laguna_nor_partitions,
130 +       .nr_parts = ARRAY_SIZE(laguna_nor_partitions),
131 +};
132 +
133 +static struct resource laguna_nor_res = {
134 +       .start = CNS3XXX_FLASH_BASE,
135 +       .end = CNS3XXX_FLASH_BASE + SZ_128M - 1,
136 +       .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
137 +};
138 +
139 +static struct platform_device laguna_nor_pdev = {
140 +       .name = "physmap-flash",
141 +       .id = 0,
142 +       .resource = &laguna_nor_res,
143 +       .num_resources = 1,
144 +       .dev = {
145 +               .platform_data = &laguna_nor_pdata,
146 +       },
147 +};
148 +
149 +/*
150 + * SPI
151 + */
152 +static struct mtd_partition laguna_spi_partitions[] = {
153 +       {
154 +               .name           = "uboot",
155 +               .size           = SZ_256K,
156 +               .offset         = 0,
157 +               .mask_flags     = MTD_WRITEABLE,
158 +       }, {
159 +               .name           = "params",
160 +               .size           = SZ_256K,
161 +               .offset         = SZ_256K,
162 +       }, {
163 +               .name           = "kernel",
164 +               .size           = SZ_1M + SZ_512K,
165 +               .offset         = SZ_512K,
166 +       }, {
167 +               .name           = "rootfs",
168 +               .size           = SZ_16M - SZ_2M,
169 +               .offset         = SZ_2M,
170 +       },
171 +};
172 +
173 +static struct flash_platform_data laguna_spi_pdata = {
174 +       .parts = laguna_spi_partitions,
175 +       .nr_parts = ARRAY_SIZE(laguna_spi_partitions),
176 +};
177 +
178 +static struct spi_board_info __initdata laguna_spi_devices[] = {
179 +       {
180 +               .modalias = "m25p80",
181 +               .platform_data = &laguna_spi_pdata,
182 +               .max_speed_hz = 50000000,
183 +               .bus_num = 1,
184 +               .chip_select = 0,
185 +       },
186 +};
187 +
188 +static struct platform_device laguna_spi_controller = {
189 +       .name = "cns3xxx_spi",
190 +};
191 +
192 +/*
193 + * LED's
194 + */
195 +static struct gpio_led laguna_gpio_leds[] = {
196 +       {
197 +               .name = "user1", /* Green Led */
198 +               .gpio = 115,
199 +               .active_low = 1,
200 +       },{
201 +               .name = "user2", /* Red Led */
202 +               .gpio = 114,
203 +               .active_low = 1,
204 +       },
205 +};
206 +
207 +static struct gpio_led_platform_data laguna_gpio_leds_data = {
208 +       .num_leds = 2,
209 +       .leds = laguna_gpio_leds,
210 +};
211 +
212 +static struct platform_device laguna_gpio_leds_device = {
213 +       .name = "leds-gpio",
214 +       .id = -1,
215 +       .dev.platform_data = &laguna_gpio_leds_data,
216 +};
217 +
218 +/*
219 + * Ethernet
220 + */
221 +static struct cns3xxx_plat_info laguna_net_data = {
222 +       .ports = 0,
223 +       .phy = {
224 +               0,
225 +               1,
226 +               2,
227 +       },
228 +};
229 +
230 +static struct platform_device laguna_net_device = {
231 +       .name = "cns3xxx_eth",
232 +       .id = 0,
233 +       .dev.platform_data = &laguna_net_data,
234 +};
235 +
236 +/*
237 + * UART
238 + */
239 +static void __init laguna_early_serial_setup(void)
240 +{
241 +#ifdef CONFIG_SERIAL_8250_CONSOLE
242 +       static struct uart_port laguna_serial_port = {
243 +               .membase        = (void __iomem *)CNS3XXX_UART0_BASE_VIRT,
244 +               .mapbase        = CNS3XXX_UART0_BASE,
245 +               .irq            = IRQ_CNS3XXX_UART0,
246 +               .iotype         = UPIO_MEM,
247 +               .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
248 +               .regshift       = 2,
249 +               .uartclk        = 24000000,
250 +               .line           = 0,
251 +               .type           = PORT_16550A,
252 +               .fifosize       = 16,
253 +       };
254 +
255 +       early_serial_setup(&laguna_serial_port);
256 +#endif
257 +}
258 +
259 +static struct resource laguna_uart_resources[] = {
260 +       {
261 +               .start = CNS3XXX_UART0_BASE,
262 +               .end   = CNS3XXX_UART0_BASE + SZ_4K - 1,
263 +               .flags    = IORESOURCE_MEM
264 +       },{
265 +               .start = CNS3XXX_UART2_BASE,
266 +               .end   = CNS3XXX_UART2_BASE + SZ_4K - 1,
267 +               .flags    = IORESOURCE_MEM
268 +       },{
269 +               .start = CNS3XXX_UART2_BASE,
270 +               .end   = CNS3XXX_UART2_BASE + SZ_4K - 1,
271 +               .flags    = IORESOURCE_MEM
272 +       },
273 +};
274 +
275 +static struct plat_serial8250_port laguna_uart_data[] = {
276 +       {
277 +               .membase        = (char*) (CNS3XXX_UART0_BASE_VIRT),
278 +               .mapbase        = (CNS3XXX_UART0_BASE),
279 +               .irq            = IRQ_CNS3XXX_UART0,
280 +               .iotype         = UPIO_MEM,
281 +               .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST,
282 +               .regshift       = 2,
283 +               .uartclk        = 24000000,
284 +               .type           = PORT_16550A,
285 +       },{
286 +               .membase        = (char*) (CNS3XXX_UART1_BASE_VIRT),
287 +               .mapbase        = (CNS3XXX_UART1_BASE),
288 +               .irq            = IRQ_CNS3XXX_UART1,
289 +               .iotype         = UPIO_MEM,
290 +               .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST,
291 +               .regshift       = 2,
292 +               .uartclk        = 24000000,
293 +               .type           = PORT_16550A,
294 +       },{
295 +               .membase        = (char*) (CNS3XXX_UART2_BASE_VIRT),
296 +               .mapbase        = (CNS3XXX_UART2_BASE),
297 +               .irq            = IRQ_CNS3XXX_UART2,
298 +               .iotype         = UPIO_MEM,
299 +               .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST,
300 +               .regshift       = 2,
301 +               .uartclk        = 24000000,
302 +               .type           = PORT_16550A,
303 +       },
304 +};
305 +
306 +static struct platform_device laguna_uart = {
307 +       .name     = "serial8250",
308 +       .id     = PLAT8250_DEV_PLATFORM,
309 +       .dev.platform_data  = laguna_uart_data,
310 +       .num_resources    = 3,
311 +       .resource   = laguna_uart_resources
312 +};
313 +
314 +/*
315 + * USB
316 + */
317 +static struct resource cns3xxx_usb_ehci_resources[] = {
318 +       [0] = {
319 +               .start = CNS3XXX_USB_BASE,
320 +               .end   = CNS3XXX_USB_BASE + SZ_16M - 1,
321 +               .flags = IORESOURCE_MEM,
322 +       },
323 +       [1] = {
324 +               .start = IRQ_CNS3XXX_USB_EHCI,
325 +               .flags = IORESOURCE_IRQ,
326 +       },
327 +};
328 +
329 +static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
330 +
331 +static struct platform_device cns3xxx_usb_ehci_device = {
332 +       .name          = "cns3xxx-ehci",
333 +       .num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
334 +       .resource      = cns3xxx_usb_ehci_resources,
335 +       .dev           = {
336 +               .dma_mask          = &cns3xxx_usb_ehci_dma_mask,
337 +               .coherent_dma_mask = DMA_BIT_MASK(32),
338 +       },
339 +};
340 +
341 +static struct resource cns3xxx_usb_ohci_resources[] = {
342 +       [0] = {
343 +               .start = CNS3XXX_USB_OHCI_BASE,
344 +               .end   = CNS3XXX_USB_OHCI_BASE + SZ_16M - 1,
345 +               .flags = IORESOURCE_MEM,
346 +       },
347 +       [1] = {
348 +               .start = IRQ_CNS3XXX_USB_OHCI,
349 +               .flags = IORESOURCE_IRQ,
350 +       },
351 +};
352 +
353 +static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
354 +
355 +static struct platform_device cns3xxx_usb_ohci_device = {
356 +       .name          = "cns3xxx-ohci",
357 +       .num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
358 +       .resource      = cns3xxx_usb_ohci_resources,
359 +       .dev           = {
360 +               .dma_mask          = &cns3xxx_usb_ohci_dma_mask,
361 +               .coherent_dma_mask = DMA_BIT_MASK(32),
362 +       },
363 +};
364 +
365 +static struct resource cns3xxx_usb_otg_resources[] = {
366 +       [0] = {
367 +               .start = CNS3XXX_USBOTG_BASE,
368 +               .end   = CNS3XXX_USBOTG_BASE + SZ_16M - 1,
369 +               .flags = IORESOURCE_MEM,
370 +       },
371 +       [1] = {
372 +               .start = IRQ_CNS3XXX_USB_OTG,
373 +               .flags = IORESOURCE_IRQ,
374 +       },
375 +};
376 +
377 +static u64 cns3xxx_usb_otg_dma_mask = DMA_BIT_MASK(32);
378 +
379 +static struct platform_device cns3xxx_usb_otg_device = {
380 +       .name          = "dwc_otg",
381 +       .num_resources = ARRAY_SIZE(cns3xxx_usb_otg_resources),
382 +       .resource      = cns3xxx_usb_otg_resources,
383 +       .dev           = {
384 +               .dma_mask          = &cns3xxx_usb_otg_dma_mask,
385 +               .coherent_dma_mask = DMA_BIT_MASK(32),
386 +       },
387 +};
388 +
389 +/*
390 + * I2C
391 + */
392 +static struct resource laguna_i2c_resource[] = {
393 +       {
394 +               .start    = CNS3XXX_SSP_BASE + 0x20,
395 +               .end      = 0x7100003f,
396 +               .flags    = IORESOURCE_MEM,
397 +       },{
398 +               .start    = IRQ_CNS3XXX_I2C,
399 +               .flags    = IORESOURCE_IRQ,
400 +       },
401 +};
402 +
403 +static struct platform_device laguna_i2c_controller = {
404 +       .name   = "cns3xxx-i2c",
405 +       .num_resources  = 2,
406 +       .resource = laguna_i2c_resource,
407 +};
408 +
409 +static struct memory_accessor *at24_mem_acc;
410 +
411 +static void at24_setup(struct memory_accessor *mem_acc, void *context)
412 +{
413 +       char buf[8];
414 +
415 +       at24_mem_acc = mem_acc;
416 +
417 +       /* Read MAC addresses */
418 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x100, 6) == 6)
419 +               memcpy(&laguna_net_data.hwaddr[0], buf, ETH_ALEN);
420 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x106, 6) == 6)
421 +               memcpy(&laguna_net_data.hwaddr[1], buf, ETH_ALEN);
422 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x10C, 6) == 6)
423 +               memcpy(&laguna_net_data.hwaddr[2], buf, ETH_ALEN);
424 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x112, 6) == 6)
425 +               memcpy(&laguna_net_data.hwaddr[3], buf, ETH_ALEN);
426 +
427 +       /* Read out Model Information */
428 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x130, 16) == 16)
429 +               memcpy(&laguna_info.model, buf, 16);
430 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x140, 1) == 1)
431 +               memcpy(&laguna_info.nor_flash_size, buf, 1);
432 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x141, 1) == 1)
433 +               memcpy(&laguna_info.spi_flash_size, buf, 1);
434 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x142, 4) == 4)
435 +               memcpy(&laguna_info.config_bitmap, buf, 4);
436 +       if (at24_mem_acc->read(at24_mem_acc, buf, 0x146, 4) == 4)
437 +               memcpy(&laguna_info.config2_bitmap, buf, 4);
438 +};
439 +
440 +static struct at24_platform_data laguna_eeprom_info = {
441 +       .byte_len = 1024,
442 +       .page_size = 16,
443 +       .flags = AT24_FLAG_READONLY,
444 +       .setup = at24_setup,
445 +};
446 +
447 +static struct pca953x_platform_data laguna_pca_data = {
448 +       .gpio_base = 100,
449 +};
450 +
451 +static struct i2c_board_info __initdata laguna_i2c_devices[] = {
452 +       {
453 +               I2C_BOARD_INFO("pca9555", 0x23),
454 +               .platform_data = &laguna_pca_data,
455 +       },{
456 +               I2C_BOARD_INFO("gsp", 0x29),
457 +       },{
458 +               I2C_BOARD_INFO ("24c08",0x50),
459 +               .platform_data = &laguna_eeprom_info,
460 +       },{
461 +               I2C_BOARD_INFO("ds1672", 0x68),
462 +       },
463 +};
464 +
465 +/*
466 + * Watchdog
467 + */
468 +
469 +static struct resource laguna_watchdog_resource[] = {
470 +       {
471 +               .start = CNS3XXX_TC11MP_TWD_BASE,
472 +               .end = CNS3XXX_TC11MP_TWD_BASE + SZ_4K - 1,
473 +               .flags = IORESOURCE_MEM,
474 +       },{
475 +               .start = IRQ_LOCALWDOG,
476 +               .end = IRQ_LOCALWDOG,
477 +               .flags = IORESOURCE_IRQ,
478 +       }
479 +};
480 +
481 +static struct platform_device laguna_watchdog = {
482 +       .name = "mpcore_wdt",
483 +       .id = -1,
484 +       .num_resources = ARRAY_SIZE(laguna_watchdog_resource),
485 +       .resource = laguna_watchdog_resource,
486 +};
487 +
488 +/*
489 + * Initialization
490 + */
491 +
492 +static void __init laguna_init(void)
493 +{
494 +       platform_device_register(&laguna_watchdog);
495 +
496 +       platform_device_register(&laguna_i2c_controller);
497 +
498 +       i2c_register_board_info(0, laguna_i2c_devices,
499 +                       ARRAY_SIZE(laguna_i2c_devices));
500 +
501 +
502 +       pm_power_off = cns3xxx_power_off;
503 +}
504 +
505 +static struct map_desc laguna_io_desc[] __initdata = {
506 +       {
507 +               .virtual        = CNS3XXX_UART0_BASE_VIRT,
508 +               .pfn            = __phys_to_pfn(CNS3XXX_UART0_BASE),
509 +               .length         = SZ_4K,
510 +               .type           = MT_DEVICE,
511 +       },{
512 +               .virtual        = CNS3XXX_UART1_BASE_VIRT,
513 +               .pfn            = __phys_to_pfn(CNS3XXX_UART1_BASE),
514 +               .length         = SZ_4K,
515 +               .type           = MT_DEVICE,
516 +       },{
517 +               .virtual        = CNS3XXX_UART2_BASE_VIRT,
518 +               .pfn            = __phys_to_pfn(CNS3XXX_UART2_BASE),
519 +               .length         = SZ_4K,
520 +               .type           = MT_DEVICE,
521 +       },
522 +};
523 +
524 +static void __init laguna_map_io(void)
525 +{
526 +       cns3xxx_map_io();
527 +       iotable_init(laguna_io_desc, ARRAY_SIZE(laguna_io_desc));
528 +
529 +       laguna_early_serial_setup();
530 +}
531 +
532 +
533 +static int __init laguna_model_setup(void)
534 +{
535 +       u32 __iomem *mem;
536 +       u32 reg;
537 +       u8 pcie_bitmap = 0;
538 +
539 +       printk("Running on Gateworks Laguna %s\n", laguna_info.model);
540 +
541 +       if (strncmp(laguna_info.model, "GW", 2) == 0) {
542 +               if (laguna_info.config_bitmap & ETH0_LOAD)
543 +                       laguna_net_data.ports |= BIT(0);
544 +               if (laguna_info.config_bitmap & ETH1_LOAD)
545 +                       laguna_net_data.ports |= BIT(1);
546 +               if (laguna_info.config_bitmap & ETH2_LOAD)
547 +                       laguna_net_data.ports |= BIT(2);
548 +               if (laguna_net_data.ports)
549 +                       platform_device_register(&laguna_net_device);
550 +
551 +               if (laguna_info.config_bitmap & (SATA0_LOAD | SATA1_LOAD))
552 +                       cns3xxx_ahci_init();
553 +
554 +               if (laguna_info.config_bitmap & (PCIE0_LOAD))
555 +                       pcie_bitmap |= 0x1;
556 +
557 +               if (laguna_info.config_bitmap & (PCIE1_LOAD))
558 +                       pcie_bitmap |= 0x2;
559 +
560 +               cns3xxx_pcie_init(pcie_bitmap);
561 +
562 +               if (laguna_info.config_bitmap & (USB0_LOAD)) {
563 +                       cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
564 +
565 +                       /* DRVVBUS pins share with GPIOA */
566 +                       mem = (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0014);
567 +                       reg = __raw_readl(mem);
568 +                       reg |= 0x8;
569 +                       __raw_writel(reg, mem);
570 +
571 +                       /* Enable OTG */
572 +                       mem = (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0808);
573 +                       reg = __raw_readl(mem);
574 +                       reg &= ~(1 << 10);
575 +                       __raw_writel(reg, mem);
576 +
577 +                       platform_device_register(&cns3xxx_usb_otg_device);
578 +               }
579 +
580 +               if (laguna_info.config_bitmap & (USB1_LOAD)) {
581 +                       platform_device_register(&cns3xxx_usb_ehci_device);
582 +                       platform_device_register(&cns3xxx_usb_ohci_device);
583 +               }
584 +
585 +               if (laguna_info.config_bitmap & (SD_LOAD))
586 +                       cns3xxx_sdhci_init();
587 +
588 +               if (laguna_info.config_bitmap & (UART0_LOAD))
589 +                       laguna_uart.num_resources = 1;
590 +               if (laguna_info.config_bitmap & (UART1_LOAD))
591 +                       laguna_uart.num_resources = 2;
592 +               if (laguna_info.config_bitmap & (UART2_LOAD))
593 +                       laguna_uart.num_resources = 3;
594 +               platform_device_register(&laguna_uart);
595 +
596 +               if (laguna_info.config2_bitmap & (NOR_FLASH_LOAD)) {
597 +                       switch (laguna_info.nor_flash_size) {
598 +                               case 1:
599 +                                       laguna_nor_partitions[3].size = SZ_8M - SZ_256K - SZ_128K - SZ_2M;
600 +                                       laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_8M - 1;
601 +                               break;
602 +                               case 2:
603 +                                       laguna_nor_partitions[3].size = SZ_16M - SZ_256K - SZ_128K - SZ_2M;
604 +                                       laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_16M - 1;
605 +                               break;
606 +                               case 3:
607 +                                       laguna_nor_partitions[3].size = SZ_32M - SZ_256K - SZ_128K - SZ_2M;
608 +                                       laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_32M - 1;
609 +                               break;
610 +                               case 4:
611 +                                       laguna_nor_partitions[3].size = SZ_64M - SZ_256K - SZ_128K - SZ_2M;
612 +                                       laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_64M - 1;
613 +                               break;
614 +                               case 5:
615 +                                       laguna_nor_partitions[3].size = SZ_128M - SZ_256K - SZ_128K - SZ_2M;
616 +                                       laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_128M - 1;
617 +                               break;
618 +                       }
619 +                       platform_device_register(&laguna_nor_pdev);
620 +               }
621 +
622 +               if (laguna_info.config2_bitmap & (SPI_FLASH_LOAD)) {
623 +                       switch (laguna_info.spi_flash_size) {
624 +                               case 1:
625 +                                       laguna_spi_partitions[3].size = SZ_4M - SZ_2M;
626 +                               break;
627 +                               case 2:
628 +                                       laguna_spi_partitions[3].size = SZ_8M - SZ_2M;
629 +                               break;
630 +                               case 3:
631 +                                       laguna_spi_partitions[3].size = SZ_16M - SZ_2M;
632 +                               break;
633 +                               case 4:
634 +                                       laguna_spi_partitions[3].size = SZ_32M - SZ_2M;
635 +                               break;
636 +                               case 5:
637 +                                       laguna_spi_partitions[3].size = SZ_64M - SZ_2M;
638 +                               break;
639 +                       }
640 +                       spi_register_board_info(laguna_spi_devices, ARRAY_SIZE(laguna_spi_devices));
641 +               }
642 +
643 +               if (laguna_info.config_bitmap & (SPI0_LOAD | SPI1_LOAD)) {
644 +                       platform_device_register(&laguna_spi_controller);
645 +               }
646 +
647 +               /*
648 +                * Do any model specific setup not known by the bitmap by matching
649 +                *  the first 6 characters of the model name
650 +                */
651 +
652 +               if (strncmp(laguna_info.model, "GW2388", 6) == 0) {
653 +                       platform_device_register(&laguna_gpio_leds_device);
654 +               } else if (strncmp(laguna_info.model, "GW2380", 6) == 0) {
655 +                       laguna_gpio_leds[0].gpio = 107;
656 +                       laguna_gpio_leds[1].gpio = 106;
657 +                       laguna_gpio_leds_data.num_leds = 2;
658 +                       platform_device_register(&laguna_gpio_leds_device);
659 +               }
660 +       } else {
661 +               // Do some defaults here, not sure what yet
662 +       }
663 +       return 0;
664 +}
665 +
666 +late_initcall(laguna_model_setup);
667 +
668 +MACHINE_START(GW2388, "Gateworks Corporation Laguna Platform")
669 +       .boot_params    = 0x00000100,
670 +       .map_io         = laguna_map_io,
671 +       .init_irq       = cns3xxx_init_irq,
672 +       .timer          = &cns3xxx_timer,
673 +       .init_machine   = laguna_init,
674 +MACHINE_END
675 --- a/arch/arm/mach-cns3xxx/Kconfig
676 +++ b/arch/arm/mach-cns3xxx/Kconfig
677 @@ -10,4 +10,13 @@ config MACH_CNS3420VB
678           This is a platform with an on-board ARM11 MPCore and has support
679           for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, etc.
680  
681 +config MACH_GW2388
682 +       bool "Support for Gateworks Laguna Platform"
683 +       select MIGHT_HAVE_PCI
684 +       help
685 +         Include support for the Gateworks Laguna Platform
686 +
687 +         This is a platform with an on-board ARM11 MPCore and has support
688 +         for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, I2C, GIG, etc.
689 +
690  endmenu
691 --- a/arch/arm/mach-cns3xxx/core.c
692 +++ b/arch/arm/mach-cns3xxx/core.c
693 @@ -16,6 +16,7 @@
694  #include <asm/mach/time.h>
695  #include <asm/mach/irq.h>
696  #include <asm/hardware/gic.h>
697 +#include <asm/smp_twd.h>
698  #include <mach/cns3xxx.h>
699  #include "core.h"
700  
701 @@ -60,11 +61,24 @@ static struct map_desc cns3xxx_io_desc[]
702                 .pfn            = __phys_to_pfn(CNS3XXX_PM_BASE),
703                 .length         = SZ_4K,
704                 .type           = MT_DEVICE,
705 +       }, {
706 +               .virtual        = CNS3XXX_SWITCH_BASE_VIRT,
707 +               .pfn            = __phys_to_pfn(CNS3XXX_SWITCH_BASE),
708 +               .length         = SZ_4K,
709 +               .type           = MT_DEVICE,
710 +       }, {
711 +               .virtual        = CNS3XXX_SSP_BASE_VIRT,
712 +               .pfn            = __phys_to_pfn(CNS3XXX_SSP_BASE),
713 +               .length         = SZ_4K,
714 +               .type           = MT_DEVICE,
715         },
716  };
717  
718  void __init cns3xxx_map_io(void)
719  {
720 +#ifdef CONFIG_LOCAL_TIMERS
721 +       twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
722 +#endif
723         iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
724  }
725  
726 --- a/arch/arm/Kconfig
727 +++ b/arch/arm/Kconfig
728 @@ -313,6 +313,7 @@ config ARCH_CLPS711X
729  config ARCH_CNS3XXX
730         bool "Cavium Networks CNS3XXX family"
731         select CPU_V6
732 +       select ARCH_WANT_OPTIONAL_GPIOLIB
733         select GENERIC_CLOCKEVENTS
734         select ARM_GIC
735         select MIGHT_HAVE_PCI
736 --- /dev/null
737 +++ b/arch/arm/mach-cns3xxx/include/mach/gpio.h
738 @@ -0,0 +1,98 @@
739 +/*
740 + * arch/arm/mach-cns3xxx/include/mach/gpio.h
741 + *
742 + * CNS3xxx GPIO wrappers for arch-neutral GPIO calls
743 + *
744 + * Copyright 2011 Gateworks Corporation
745 + *               Chris Lang <clang@gateworks.com>
746 + *
747 + * Based on IXP implementation by Milan Svoboda <msvoboda@ra.rockwell.com>
748 + * Based on PXA implementation by Philipp Zabel <philipp.zabel@gmail.com>
749 + *
750 + * This program is free software; you can redistribute it and/or modify
751 + * it under the terms of the GNU General Public License as published by
752 + * the Free Software Foundation; either version 2 of the License, or
753 + * (at your option) any later version.
754 + *
755 + * This program is distributed in the hope that it will be useful,
756 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
757 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
758 + * GNU General Public License for more details.
759 + *
760 + * You should have received a copy of the GNU General Public License
761 + * along with this program; if not, write to the Free Software
762 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
763 + *
764 + */
765 +
766 +#ifndef __ASM_ARCH_CNS3XXX_GPIO_H
767 +#define __ASM_ARCH_CNS3XXX_GPIO_H
768 +
769 +#include <linux/kernel.h>
770 +#include <linux/io.h>
771 +#include <mach/hardware.h>
772 +#include <asm-generic/gpio.h>                  /* cansleep wrappers */
773 +
774 +#define NR_BUILTIN_GPIO 64
775 +
776 +#define CNS3XXX_GPIO_IN    0x0
777 +#define CNS3XXX_GPIO_OUT   0x1
778 +
779 +#define CNS3XXX_GPIO_LO   0
780 +#define CNS3XXX_GPIO_HI   1
781 +
782 +#define CNS3XXX_GPIO_OUTPUT         0x00
783 +#define CNS3XXX_GPIO_INPUT          0x04
784 +#define CNS3XXX_GPIO_DIR            0x08
785 +#define CNS3XXX_GPIO_SET            0x10
786 +#define CNS3XXX_GPIO_CLEAR          0x14
787 +
788 +static inline void gpio_line_get(u8 line, int *value)
789 +{
790 +       if (line < 32)
791 +               *value = ((__raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> line) & 0x1);
792 +       else
793 +               *value = ((__raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> (line - 32)) & 0x1);
794 +}
795 +
796 +static inline void gpio_line_set(u8 line, int value)
797 +{
798 +       if (line < 32) {
799 +               if (value)
800 +                       __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_SET);
801 +               else
802 +                       __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
803 +       } else {
804 +               if (value)
805 +                       __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_SET);
806 +               else
807 +                       __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
808 +       }
809 +}
810 +
811 +static inline int gpio_get_value(unsigned gpio)
812 +{
813 +       if (gpio < NR_BUILTIN_GPIO)
814 +       {
815 +               int value;
816 +               gpio_line_get(gpio, &value);
817 +               return value;
818 +       }
819 +       else
820 +               return __gpio_get_value(gpio);
821 +}
822 +
823 +static inline void gpio_set_value(unsigned gpio, int value)
824 +{
825 +       if (gpio < NR_BUILTIN_GPIO)
826 +               gpio_line_set(gpio, value);
827 +       else
828 +               __gpio_set_value(gpio, value);
829 +}
830 +
831 +#define gpio_cansleep __gpio_cansleep
832 +
833 +extern int gpio_to_irq(int gpio);
834 +extern int irq_to_gpio(int gpio);
835 +
836 +#endif
837 --- a/arch/arm/mach-cns3xxx/Makefile
838 +++ b/arch/arm/mach-cns3xxx/Makefile
839 @@ -1,6 +1,7 @@
840  obj-$(CONFIG_ARCH_CNS3XXX)             += core.o pm.o devices.o
841  obj-$(CONFIG_PCI)                      += pcie.o
842  obj-$(CONFIG_MACH_CNS3420VB)           += cns3420vb.o
843 +obj-$(CONFIG_MACH_GW2388)              += laguna.o
844  obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
845  obj-$(CONFIG_HOTPLUG_CPU)              += hotplug.o
846  obj-$(CONFIG_LOCAL_TIMERS)             += localtimer.o
847 --- a/arch/arm/tools/mach-types
848 +++ b/arch/arm/tools/mach-types
849 @@ -438,6 +438,7 @@ icontrol            MACH_ICONTROL           ICONTROL                2624
850  qsd8x50a_st1_5         MACH_QSD8X50A_ST1_5     QSD8X50A_ST1_5          2627
851  mx23evk                        MACH_MX23EVK            MX23EVK                 2629
852  ap4evb                 MACH_AP4EVB             AP4EVB                  2630
853 +gw2388                 MACH_GW2388             GW2388                  2635
854  mityomapl138           MACH_MITYOMAPL138       MITYOMAPL138            2650
855  guruplug               MACH_GURUPLUG           GURUPLUG                2659
856  spear310               MACH_SPEAR310           SPEAR310                2660
857 --- a/arch/arm/mach-cns3xxx/pcie.c
858 +++ b/arch/arm/mach-cns3xxx/pcie.c
859 @@ -365,7 +365,7 @@ static int cns3xxx_pcie_abort_handler(un
860         return 0;
861  }
862  
863 -static int __init cns3xxx_pcie_init(void)
864 +int cns3xxx_pcie_init(u8 bitmap)
865  {
866         int i;
867  
868 @@ -373,6 +373,9 @@ static int __init cns3xxx_pcie_init(void
869                         "imprecise external abort");
870  
871         for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
872 +               if (!(bitmap & (1 << i)))
873 +                       continue;
874 +
875                 iotable_init(cns3xxx_pcie[i].cfg_bases,
876                              ARRAY_SIZE(cns3xxx_pcie[i].cfg_bases));
877                 cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i));
878 @@ -386,4 +389,3 @@ static int __init cns3xxx_pcie_init(void
879  
880         return 0;
881  }
882 -device_initcall(cns3xxx_pcie_init);
883 --- a/arch/arm/mach-cns3xxx/cns3420vb.c
884 +++ b/arch/arm/mach-cns3xxx/cns3420vb.c
885 @@ -175,6 +175,8 @@ static void __init cns3420_init(void)
886         cns3xxx_ahci_init();
887         cns3xxx_sdhci_init();
888  
889 +       cns3xxx_pcie_init(0x3);
890 +
891         pm_power_off = cns3xxx_power_off;
892  }
893  
894 --- a/arch/arm/mach-cns3xxx/include/mach/platform.h
895 +++ b/arch/arm/mach-cns3xxx/include/mach/platform.h
896 @@ -22,5 +22,7 @@ struct cns3xxx_plat_info {
897         u32 phy[3];
898  };
899  
900 +extern int cns3xxx_pcie_init(u8 bitmap);
901 +
902  #endif /* __ASM_ARCH_PLATFORM_H */
903  #endif