ARM: LPC32XX: NAND related updates
[linux-2.6.34-lpc32xx.git] / arch / arm / mach-lpc32xx / fdi3250.c
1 /*
2  * arch/arm/mach-lpc32xx/fdi3250.c
3  *
4  * Copyright (C) 2010 NXP Semiconductors
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/init.h>
18 #include <linux/platform_device.h>
19 #include <linux/sysdev.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22 #include <linux/dma-mapping.h>
23 #include <linux/device.h>
24 #include <linux/delay.h>
25 #include <linux/spi/spi.h>
26 #include <linux/spi/eeprom.h>
27 #include <linux/leds.h>
28 #include <linux/gpio.h>
29 #include <linux/input.h>
30 #include <linux/amba/bus.h>
31 #include <linux/amba/clcd.h>
32 #include <linux/amba/pl022.h>
33 #include <linux/amba/mmci.h>
34
35 #include <asm/setup.h>
36 #include <asm/mach-types.h>
37 #include <asm/mach/arch.h>
38
39 #include <mach/hardware.h>
40 #include <mach/platform.h>
41 #include <mach/board.h>
42 #include "common.h"
43
44 /*
45  * Mapped GPIOLIB GPIOs
46  */
47 #define LED_GPIO                LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 3)
48 #define SPI_CS_GPIO             LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
49 #define NAND_WP_GPIO            LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 19)
50
51 /*
52  * Tick LED
53  */
54 static struct gpio_led phy_leds[] = {
55         {
56                 .name                   = "led0",
57                 .gpio                   = LED_GPIO,
58                 .active_low             = 1,
59                 .default_trigger        = "heartbeat",
60         },
61 };
62
63 static struct gpio_led_platform_data led_data = {
64         .leds = phy_leds,
65         .num_leds = ARRAY_SIZE(phy_leds),
66 };
67
68 static struct platform_device lpc32xx_gpio_led_device = {
69         .name                   = "leds-gpio",
70         .id                     = -1,
71         .dev.platform_data      = &led_data,
72 };
73
74 /*
75  * AMBA SSP (SPI)
76  */
77 static struct pl022_ssp_controller lpc32xx_ssp0_data = {
78         .bus_id                 = 0,
79         .num_chipselect         = 2,
80         .enable_dma             = 0,
81 };
82
83 static struct amba_device lpc32xx_ssp0_device = {
84         .dev    = {
85                 .coherent_dma_mask      = ~0,
86                 .init_name              = "dev:ssp0",
87                 .platform_data          = &lpc32xx_ssp0_data,
88         },
89         .res                            = {
90                 .start                  = LPC32XX_SSP0_BASE,
91                 .end                    = (LPC32XX_SSP0_BASE + SZ_4K - 1),
92                 .flags                  = IORESOURCE_MEM,
93         },
94         .dma_mask                       = ~0,
95         .irq                            = {IRQ_LPC32XX_SSP0, NO_IRQ},
96 };
97
98 /* SPIDEV chip select function */
99 static void fdi3250_spi_cs_set(u32 control)
100 {
101         gpio_set_value(SPI_CS_GPIO, (int) control);
102 }
103
104 /* SPIDEV parameters */
105 static struct pl022_config_chip spi0_chip_info = {
106         .lbm                    = LOOPBACK_DISABLED,
107         .com_mode               = INTERRUPT_TRANSFER,
108         .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
109         .hierarchy              = SSP_MASTER,
110         .slave_tx_disable       = 0,
111         .endian_tx              = SSP_TX_LSB,
112         .endian_rx              = SSP_RX_LSB,
113         .data_size              = SSP_DATA_BITS_8,
114         .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
115         .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
116         .clk_phase              = SSP_CLK_FIRST_EDGE,
117         .clk_pol                = SSP_CLK_POL_IDLE_LOW,
118         .ctrl_len               = SSP_BITS_8,
119         .wait_state             = SSP_MWIRE_WAIT_ZERO,
120         .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
121         .cs_control             = fdi3250_spi_cs_set,
122 };
123
124 /* SPI devices registration */
125 static int __init fdi3250_spi_devices_register(void)
126 {
127         static struct spi_board_info info[] = {
128                 {
129                         .modalias = "spidev",
130                         .max_speed_hz = 2500000,
131                         .bus_num = 0,
132                         .chip_select = 0,
133                         .controller_data = &spi0_chip_info,
134                 },
135         };
136
137         return spi_register_board_info(info, ARRAY_SIZE(info));
138 }
139 arch_initcall(fdi3250_spi_devices_register);
140
141 #if defined (CONFIG_FB_ARMCLCD)
142 /*
143  * Board specific LCD setup and functions
144  */
145 #if defined (CONFIG_SOM9DIMM3250_LCD_PANEL)
146 /*
147  * Support for QVGA portrait panel 
148  */
149 #if defined (CONFIG_SOM9DIMM3250_LCD_TOSHIBA_QVGA_35)
150 static struct clcd_panel conn_lcd_panel = {
151         .mode           = {
152                 .name           = "QVGA portrait",
153                 .refresh        = 30,
154                 .xres           = 320,
155                 .yres           = 240,
156                 .pixclock       = 158730,
157                 .left_margin    = 11,
158                 .right_margin   = 3,
159                 .upper_margin   = 7,
160                 .lower_margin   = 7,
161                 .hsync_len      = 69,
162                 .vsync_len      = 45,
163                 .sync           = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
164                 .vmode          = FB_VMODE_NONINTERLACED,
165         },
166         .width          = -1,
167         .height         = -1,
168         .tim2           = 0, 
169         .cntl           = (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
170                                 CNTL_LCDBPP16_565),
171         .bpp            = 16,
172 };
173 #define PANEL_SIZE (3 * SZ_64K)
174 #endif
175 #if defined (CONFIG_SOM9DIMM3250_LCD_OKAYA_VGA_35)
176 static struct clcd_panel conn_lcd_panel = {
177         .mode           = {
178                 .name           = "VGA portrait",
179                 .refresh        = 30,
180                 .xres           = 640,
181                 .yres           = 480,
182                 .pixclock       = 41666,
183                 .left_margin    = 10,
184                 .right_margin   = 120,
185                 .upper_margin   = 7,
186                 .lower_margin   = 35,
187                 .hsync_len      = 30,
188                 .vsync_len      = 3,
189                 .sync           = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
190                 .vmode          = FB_VMODE_NONINTERLACED,
191         },
192         .width          = -1,
193         .height         = -1,
194         .tim2           = 0, 
195         .cntl           = (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
196                                 CNTL_LCDBPP16_565),
197         .bpp            = 16,
198 };
199 #define PANEL_SIZE (10 * SZ_64K)
200 #endif
201
202 #endif // CONFIG_SOM9DIMM3250_LCD_PANEL
203
204 static int lpc32xx_clcd_setup(struct clcd_fb *fb)
205 {
206         dma_addr_t dma;
207
208         fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
209                         PANEL_SIZE, &dma, GFP_KERNEL);
210         if (!fb->fb.screen_base) {
211                 printk(KERN_ERR "CLCD: unable to map framebuffer\n");
212                 return -ENOMEM;
213         }
214
215         fb->fb.fix.smem_start = dma;
216         fb->fb.fix.smem_len = PANEL_SIZE;
217         fb->panel = &conn_lcd_panel;
218
219         return 0;
220 }
221
222 static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
223 {
224         return dma_mmap_writecombine(&fb->dev->dev, vma,
225                                      fb->fb.screen_base,
226                                      fb->fb.fix.smem_start,
227                                      fb->fb.fix.smem_len);
228 }
229
230 static void lpc32xx_clcd_remove(struct clcd_fb *fb)
231 {
232         dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
233                               fb->fb.screen_base, fb->fb.fix.smem_start);
234 }
235
236 void clcd_disable(struct clcd_fb *fb)
237 {
238 #if defined (CONFIG_SOM9DIMM3250_LCD_TOSHIBA_QVGA_35)
239         __raw_writel(0x40000000, io_p2v(LPC32XX_PWM1_BASE));
240 #elif defined (CONFIG_SOM9DIMM3250_LCD_OKAYA_VGA_35)
241         __raw_writel(0x00000000, io_p2v(LPC32XX_PWM1_BASE));
242 #endif
243 }
244
245 void clcd_enable(struct clcd_fb *fb)
246 {
247 #if defined (CONFIG_SOM9DIMM3250_LCD_TOSHIBA_QVGA_35)
248         __raw_writel(0x00000000, io_p2v(LPC32XX_PWM1_BASE));
249 #elif defined (CONFIG_SOM9DIMM3250_LCD_OKAYA_VGA_35)
250         __raw_writel(0x40000000, io_p2v(LPC32XX_PWM1_BASE));
251 #endif
252 }
253
254 struct clcd_board lpc32xx_clcd_data = {
255 #if defined (CONFIG_SOM9DIMM3250_LCD_TOSHIBA_QVGA_35)
256         .name           = "Toshiba 3.5 inch LCD",
257 #elif defined (CONFIG_SOM9DIMM3250_LCD_OKAYA_VGA_35)
258         .name           = "Okaya 3.5 inch LCD",
259 #else
260         .name           = "Unknown Display",
261 #endif
262         .check          = clcdfb_check,
263         .decode         = clcdfb_decode,
264         .disable        = clcd_disable,
265         .enable         = clcd_enable,
266         .setup          = lpc32xx_clcd_setup,
267         .mmap           = lpc32xx_clcd_mmap,
268         .remove         = lpc32xx_clcd_remove,
269 };
270
271 struct amba_device lpc32xx_clcd_device = {
272         .dev                            = {
273                 .coherent_dma_mask      = ~0,
274                 .init_name              = "dev:clcd",
275                 .platform_data          = &lpc32xx_clcd_data,
276         },
277         .res                            = {
278                 .start                  = LPC32XX_LCD_BASE,
279                 .end                    = (LPC32XX_LCD_BASE + SZ_4K - 1),
280                 .flags                  = IORESOURCE_MEM,
281         },
282         .dma_mask                       = ~0,
283         .irq                            = {IRQ_LPC32XX_LCD, NO_IRQ},
284 };
285 #endif
286
287 /* AMBA based devices list */
288 static struct amba_device *amba_devs[] __initdata = {
289         &lpc32xx_ssp0_device,
290 #if defined (CONFIG_FB_ARMCLCD)
291         &lpc32xx_clcd_device,
292 #endif
293 };
294
295 /*
296  * Register AMBA BUS Devices.
297  * Call AMBA device restration after SPI driver probe(),
298  * as LCD controller uses SPI driver for initialization
299  */
300 static int __init fdi3250_amba_devices_register(void)
301 {
302         u32 i = 0;
303
304         /* Add AMBA devices */
305         for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
306                 struct amba_device *d = amba_devs[i];
307                 amba_device_register(d, &iomem_resource);
308         }
309         
310         return 0;
311 }
312 device_initcall_sync(fdi3250_amba_devices_register);
313
314 #if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
315 /*
316  *  * Board specific NAND setup data
317  *   */
318 static int nandwp_enable(int enable)
319 {
320         if (enable != 0)
321                 gpio_set_value(NAND_WP_GPIO,0);
322         else
323                 gpio_set_value(NAND_WP_GPIO,1);
324
325         return 1;
326 }
327 #define BLK_SIZE (2048 * 64)
328 static struct mtd_partition __initdata fdi3250_nand_partition[] = {
329         {
330                 .name   = "fdi3250-boot",
331                 .offset = 0,
332                 .size   = (BLK_SIZE * 4)
333         },
334         {
335                 .name   = "fdi3250-uboot",
336                 .offset = MTDPART_OFS_APPEND,
337                 .size   = (BLK_SIZE * 6)
338         },
339         {
340                 .name   = "fdi3250-kernel",
341                 .offset = MTDPART_OFS_APPEND,
342                 .size   = (BLK_SIZE * 32)
343         },
344         {
345                 .name   = "fdi3250-jffs2",
346                 .offset = MTDPART_OFS_APPEND,
347                 .size   = MTDPART_SIZ_FULL
348         },
349 };
350 static struct mtd_partition * __init fdi3250_nand_partitions(int size, int *num_partitions)
351 {
352         *num_partitions = ARRAY_SIZE(fdi3250_nand_partition);
353         return fdi3250_nand_partition;
354 }
355 struct lpc32XX_nand_cfg lpc32xx_nandcfg =
356 {
357         .wdr_clks               = 14,
358         .wwidth                 = 260000000,
359         .whold                  = 104000000,
360         .wsetup                 = 200000000,
361         .rdr_clks               = 14,
362         .rwidth                 = 34666666,
363         .rhold                  = 104000000,
364         .rsetup                 = 200000000,
365         .use16bus               = 0,
366         .enable_write_prot      = nandwp_enable,
367         .partition_info         = fdi3250_nand_partitions,
368 };
369
370 /*
371  *  * SLC NAND resources
372  *   */
373 static struct resource slc_nand_resources[] = {
374         [0] = {
375                 .start  = LPC32XX_SLC_BASE,
376                 .end    = LPC32XX_SLC_BASE + SZ_4K - 1,
377                 .flags  = IORESOURCE_MEM,
378         },
379
380         [1] = {
381                 .start  = IRQ_LPC32XX_FLASH,
382                 .end    = IRQ_LPC32XX_FLASH,
383                 .flags  = IORESOURCE_IRQ,
384         },
385
386 };
387
388 static u64 lpc32xx_slc_dma_mask = 0xffffffffUL;
389 static struct platform_device lpc32xx_slc_nand_device = {
390         .name           = "lpc32xx-nand",
391         .id             = 0,
392         .dev            = {
393                                 .platform_data  = &lpc32xx_nandcfg,
394                                 .dma_mask    = &lpc32xx_slc_dma_mask,
395                                 .coherent_dma_mask = ~0UL,
396
397         },
398         .num_resources  = ARRAY_SIZE(slc_nand_resources),
399         .resource       = slc_nand_resources,
400 };
401 #endif
402
403 /*
404  * Network Support
405  */
406 static struct lpc_net_cfg lpc32xx_netdata =
407 {
408         .phy_irq        = -1,
409         .phy_mask       = 0xFFFFFFF0,
410 };
411
412 static struct resource net_resources[] = {
413         [0] = {
414                 .start  = LPC32XX_ETHERNET_BASE,
415                 .end    = LPC32XX_ETHERNET_BASE + SZ_4K - 1,
416                 .flags  = IORESOURCE_MEM,
417         },
418
419         [1] = {
420                 .start  = IRQ_LPC32XX_ETHERNET,
421                 .end    = IRQ_LPC32XX_ETHERNET,
422                 .flags  = IORESOURCE_IRQ,
423         },
424
425 };
426
427 static u64 lpc32xx_mac_dma_mask = 0xffffffffUL;
428 static struct platform_device lpc32xx_net_device = {
429         .name           = "lpc-net",
430         .id             = 0,
431         .dev            = {
432                 .dma_mask = &lpc32xx_mac_dma_mask,
433                 .coherent_dma_mask = 0xffffffffUL,
434                 .platform_data  = &lpc32xx_netdata,
435         },
436         .num_resources  = ARRAY_SIZE(net_resources),
437         .resource       = net_resources,
438 };
439
440 static struct platform_device* fdi3250_devs[] __initdata = {
441         &lpc32xx_i2c0_device,
442         &lpc32xx_i2c1_device,
443         &lpc32xx_i2c2_device,
444         &lpc32xx_watchdog_device,
445         &lpc32xx_gpio_led_device,
446         &lpc32xx_rtc_device,
447         &lpc32xx_net_device,
448 #if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
449         &lpc32xx_slc_nand_device,
450 #endif
451 #if defined(CONFIG_USB_OHCI_HCD)
452         &lpc32xx_ohci_device,
453 #endif
454 #if defined(CONFIG_USB_GADGET_LPC32XX)
455         &lpc32xx_usbd_device,
456 #endif
457 };
458
459 /*
460  * Board specific functions
461  */
462 void __init fdi3250_board_init(void)
463 {
464         u32 tmp;
465
466         /* Intiliase GPIO */
467         lpc32xx_gpio_init();
468
469         /* Set SPI CS GPIO to output */
470         gpio_request(SPI_CS_GPIO, "spi0 cs");
471         gpio_direction_output(SPI_CS_GPIO, 1);
472
473         gpio_request(NAND_WP_GPIO, "NAND WP GPIO");
474         gpio_direction_input(NAND_WP_GPIO);
475
476         /* Setup network interface for RMII mode */
477         tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
478         tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
479         tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
480         __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
481
482         /* Setup SLC NAND controller */
483         __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
484                         LPC32XX_CLKPWR_NAND_CLK_CTRL);
485
486         /* Setup LCD muxing to RGB565 */
487         tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
488                 ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
489                                 LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
490         tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
491         __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
492
493         /* Set up I2C pull levels */
494         tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
495         tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
496                 LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
497         __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
498
499         /* Initalise Serial device */
500         lpc32xx_serial_init();
501
502         /*
503          * AMBA peripheral clocks need to be enabled prior to AMBA device
504          * detection or a data fault will occur, so enable the clocks
505          * here. However, we don't want to enable them if the peripheral
506          * isn't included in the image
507          */
508         /* Initialise SSP clock */
509         tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
510         __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
511                         LPC32XX_CLKPWR_SSP_CLK_CTRL);
512
513         /* Initialise LCD clock */
514         tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
515         __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
516                         LPC32XX_CLKPWR_LCDCLK_CTRL);
517
518         /* Enable SD card clock so AMBA driver will work correctly. The
519            AMBA driver needs the clock before the SD card controller
520            driver initializes it. The clock will turn off once the driver
521            has been initialized. */
522         tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
523         tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
524                 LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
525         __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
526
527         /* Disable UART5->USB transparent mode or USB won't work */
528         tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
529         tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB;
530         __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
531
532         /* Add platform devcies */
533         platform_add_devices(fdi3250_devs, ARRAY_SIZE(fdi3250_devs));
534 }
535
536 static int __init lpc32xx_display_uid(void)
537 {
538         u32 uid[4];
539
540         lpc32xx_get_uid(uid);
541
542         printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
543                         uid[3], uid[2], uid[1], uid[0]);
544
545         return 1;
546 }
547 arch_initcall(lpc32xx_display_uid);
548
549 MACHINE_START (FDI3250, "Future Designs board with the LPC3250 Microcontroller")
550         .phys_io        = LPC32XX_UART5_BASE,
551         .io_pg_offst    = ((IO_ADDRESS(LPC32XX_HS_UART1_BASE))>>18) & 0xfffc,
552         .boot_params    = 0x80000100,
553         .map_io         = lpc32xx_map_io,
554         .init_irq       = lpc32xx_init_irq,
555         .timer          = &lpc32xx_timer,
556         .init_machine   = fdi3250_board_init,
557         MACHINE_END
558
559 /* For backwards compatibility with older bootloaders only */
560 MACHINE_START (LPC3XXX, "Future Designs board with the LPC3250 Microcontroller")
561         .phys_io        = LPC32XX_UART5_BASE,
562         .io_pg_offst    = ((IO_ADDRESS(LPC32XX_HS_UART1_BASE))>>18) & 0xfffc,
563         .boot_params    = 0x80000100,
564         .map_io         = lpc32xx_map_io,
565         .init_irq       = lpc32xx_init_irq,
566         .timer          = &lpc32xx_timer,
567         .init_machine   = fdi3250_board_init,
568         MACHINE_END