upgrade to 2.6.39
[openwrt/openwrt.git] / target / linux / cns3xxx / patches / 100-laguna_support.patch
1 --- /dev/null
2 +++ b/arch/arm/mach-cns3xxx/laguna.c
3 @@ -0,0 +1,670 @@
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_data.num_leds = 1;
657 + platform_device_register(&laguna_gpio_leds_device);
658 + }
659 + } else {
660 + // Do some defaults here, not sure what yet
661 + }
662 + return 0;
663 +}
664 +
665 +late_initcall(laguna_model_setup);
666 +
667 +MACHINE_START(GW2388, "Gateworks Corporation Laguna Platform")
668 + .boot_params = 0x00000100,
669 + .map_io = laguna_map_io,
670 + .init_irq = cns3xxx_init_irq,
671 + .timer = &cns3xxx_timer,
672 + .init_machine = laguna_init,
673 +MACHINE_END
674 --- a/arch/arm/mach-cns3xxx/Kconfig
675 +++ b/arch/arm/mach-cns3xxx/Kconfig
676 @@ -10,4 +10,13 @@ config MACH_CNS3420VB
677 This is a platform with an on-board ARM11 MPCore and has support
678 for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, etc.
679
680 +config MACH_GW2388
681 + bool "Support for Gateworks Laguna Platform"
682 + select MIGHT_HAVE_PCI
683 + help
684 + Include support for the Gateworks Laguna Platform
685 +
686 + This is a platform with an on-board ARM11 MPCore and has support
687 + for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, I2C, GIG, etc.
688 +
689 endmenu
690 --- a/arch/arm/mach-cns3xxx/core.c
691 +++ b/arch/arm/mach-cns3xxx/core.c
692 @@ -16,6 +16,7 @@
693 #include <asm/mach/time.h>
694 #include <asm/mach/irq.h>
695 #include <asm/hardware/gic.h>
696 +#include <asm/smp_twd.h>
697 #include <mach/cns3xxx.h>
698 #include "core.h"
699
700 @@ -60,11 +61,24 @@ static struct map_desc cns3xxx_io_desc[]
701 .pfn = __phys_to_pfn(CNS3XXX_PM_BASE),
702 .length = SZ_4K,
703 .type = MT_DEVICE,
704 + }, {
705 + .virtual = CNS3XXX_SWITCH_BASE_VIRT,
706 + .pfn = __phys_to_pfn(CNS3XXX_SWITCH_BASE),
707 + .length = SZ_4K,
708 + .type = MT_DEVICE,
709 + }, {
710 + .virtual = CNS3XXX_SSP_BASE_VIRT,
711 + .pfn = __phys_to_pfn(CNS3XXX_SSP_BASE),
712 + .length = SZ_4K,
713 + .type = MT_DEVICE,
714 },
715 };
716
717 void __init cns3xxx_map_io(void)
718 {
719 +#ifdef CONFIG_LOCAL_TIMERS
720 + twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
721 +#endif
722 iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
723 }
724
725 --- a/arch/arm/Kconfig
726 +++ b/arch/arm/Kconfig
727 @@ -313,6 +313,7 @@ config ARCH_CLPS711X
728 config ARCH_CNS3XXX
729 bool "Cavium Networks CNS3XXX family"
730 select CPU_V6
731 + select ARCH_WANT_OPTIONAL_GPIOLIB
732 select GENERIC_CLOCKEVENTS
733 select ARM_GIC
734 select MIGHT_HAVE_PCI
735 --- /dev/null
736 +++ b/arch/arm/mach-cns3xxx/include/mach/gpio.h
737 @@ -0,0 +1,98 @@
738 +/*
739 + * arch/arm/mach-cns3xxx/include/mach/gpio.h
740 + *
741 + * CNS3xxx GPIO wrappers for arch-neutral GPIO calls
742 + *
743 + * Copyright 2011 Gateworks Corporation
744 + * Chris Lang <clang@gateworks.com>
745 + *
746 + * Based on IXP implementation by Milan Svoboda <msvoboda@ra.rockwell.com>
747 + * Based on PXA implementation by Philipp Zabel <philipp.zabel@gmail.com>
748 + *
749 + * This program is free software; you can redistribute it and/or modify
750 + * it under the terms of the GNU General Public License as published by
751 + * the Free Software Foundation; either version 2 of the License, or
752 + * (at your option) any later version.
753 + *
754 + * This program is distributed in the hope that it will be useful,
755 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
756 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
757 + * GNU General Public License for more details.
758 + *
759 + * You should have received a copy of the GNU General Public License
760 + * along with this program; if not, write to the Free Software
761 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
762 + *
763 + */
764 +
765 +#ifndef __ASM_ARCH_CNS3XXX_GPIO_H
766 +#define __ASM_ARCH_CNS3XXX_GPIO_H
767 +
768 +#include <linux/kernel.h>
769 +#include <linux/io.h>
770 +#include <mach/hardware.h>
771 +#include <asm-generic/gpio.h> /* cansleep wrappers */
772 +
773 +#define NR_BUILTIN_GPIO 64
774 +
775 +#define CNS3XXX_GPIO_IN 0x0
776 +#define CNS3XXX_GPIO_OUT 0x1
777 +
778 +#define CNS3XXX_GPIO_LO 0
779 +#define CNS3XXX_GPIO_HI 1
780 +
781 +#define CNS3XXX_GPIO_OUTPUT 0x00
782 +#define CNS3XXX_GPIO_INPUT 0x04
783 +#define CNS3XXX_GPIO_DIR 0x08
784 +#define CNS3XXX_GPIO_SET 0x10
785 +#define CNS3XXX_GPIO_CLEAR 0x14
786 +
787 +static inline void gpio_line_get(u8 line, int *value)
788 +{
789 + if (line < 32)
790 + *value = ((__raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> line) & 0x1);
791 + else
792 + *value = ((__raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> (line - 32)) & 0x1);
793 +}
794 +
795 +static inline void gpio_line_set(u8 line, int value)
796 +{
797 + if (line < 32) {
798 + if (value)
799 + __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_SET);
800 + else
801 + __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
802 + } else {
803 + if (value)
804 + __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_SET);
805 + else
806 + __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
807 + }
808 +}
809 +
810 +static inline int gpio_get_value(unsigned gpio)
811 +{
812 + if (gpio < NR_BUILTIN_GPIO)
813 + {
814 + int value;
815 + gpio_line_get(gpio, &value);
816 + return value;
817 + }
818 + else
819 + return __gpio_get_value(gpio);
820 +}
821 +
822 +static inline void gpio_set_value(unsigned gpio, int value)
823 +{
824 + if (gpio < NR_BUILTIN_GPIO)
825 + gpio_line_set(gpio, value);
826 + else
827 + __gpio_set_value(gpio, value);
828 +}
829 +
830 +#define gpio_cansleep __gpio_cansleep
831 +
832 +extern int gpio_to_irq(int gpio);
833 +extern int irq_to_gpio(int gpio);
834 +
835 +#endif
836 --- a/arch/arm/mach-cns3xxx/Makefile
837 +++ b/arch/arm/mach-cns3xxx/Makefile
838 @@ -1,6 +1,7 @@
839 obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm.o devices.o
840 obj-$(CONFIG_PCI) += pcie.o
841 obj-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o
842 +obj-$(CONFIG_MACH_GW2388) += laguna.o
843 obj-$(CONFIG_SMP) += platsmp.o headsmp.o
844 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
845 obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
846 --- a/arch/arm/tools/mach-types
847 +++ b/arch/arm/tools/mach-types
848 @@ -438,6 +438,7 @@ icontrol MACH_ICONTROL ICONTROL 2624
849 qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627
850 mx23evk MACH_MX23EVK MX23EVK 2629
851 ap4evb MACH_AP4EVB AP4EVB 2630
852 +gw2388 MACH_GW2388 GW2388 2635
853 mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650
854 guruplug MACH_GURUPLUG GURUPLUG 2659
855 spear310 MACH_SPEAR310 SPEAR310 2660
856 --- a/arch/arm/mach-cns3xxx/pcie.c
857 +++ b/arch/arm/mach-cns3xxx/pcie.c
858 @@ -365,7 +365,7 @@ static int cns3xxx_pcie_abort_handler(un
859 return 0;
860 }
861
862 -static int __init cns3xxx_pcie_init(void)
863 +int cns3xxx_pcie_init(u8 bitmap)
864 {
865 int i;
866
867 @@ -373,6 +373,9 @@ static int __init cns3xxx_pcie_init(void
868 "imprecise external abort");
869
870 for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
871 + if (!(bitmap & (1 << i)))
872 + continue;
873 +
874 iotable_init(cns3xxx_pcie[i].cfg_bases,
875 ARRAY_SIZE(cns3xxx_pcie[i].cfg_bases));
876 cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i));
877 @@ -386,4 +389,3 @@ static int __init cns3xxx_pcie_init(void
878
879 return 0;
880 }
881 -device_initcall(cns3xxx_pcie_init);
882 --- a/arch/arm/mach-cns3xxx/cns3420vb.c
883 +++ b/arch/arm/mach-cns3xxx/cns3420vb.c
884 @@ -175,6 +175,8 @@ static void __init cns3420_init(void)
885 cns3xxx_ahci_init();
886 cns3xxx_sdhci_init();
887
888 + cns3xxx_pcie_init(0x3);
889 +
890 pm_power_off = cns3xxx_power_off;
891 }
892
893 --- a/arch/arm/mach-cns3xxx/include/mach/platform.h
894 +++ b/arch/arm/mach-cns3xxx/include/mach/platform.h
895 @@ -22,5 +22,7 @@ struct cns3xxx_plat_info {
896 u32 phy[3];
897 };
898
899 +extern int cns3xxx_pcie_init(u8 bitmap);
900 +
901 #endif /* __ASM_ARCH_PLATFORM_H */
902 #endif