[cns3xxx]: fixup second led, patch from Chris
[openwrt/svn-archive/archive.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