ARM: LPC32XX: Adding SD-Card support for FDI3250 board
[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 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 * 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_tsc_device,
448         &lpc32xx_net_device,
449 #if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
450         &lpc32xx_slc_nand_device,
451 #endif
452 #if defined(CONFIG_USB_OHCI_HCD)
453         &lpc32xx_ohci_device,
454 #endif
455 #if defined(CONFIG_USB_GADGET_LPC32XX)
456         &lpc32xx_usbd_device,
457 #endif
458 };
459
460 /*
461  * Board specific functions
462  */
463 void __init fdi3250_board_init(void)
464 {
465         u32 tmp;
466
467         /* Intiliase GPIO */
468         lpc32xx_gpio_init();
469
470         /* Set SPI CS GPIO to output */
471         gpio_request(SPI_CS_GPIO, "spi0 cs");
472         gpio_direction_output(SPI_CS_GPIO, 1);
473
474         gpio_request(NAND_WP_GPIO, "NAND WP GPIO");
475         gpio_direction_input(NAND_WP_GPIO);
476
477         /* Setup network interface for RMII mode */
478         tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
479         tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
480         tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
481         __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
482
483         /* Setup SLC NAND controller */
484         __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
485                         LPC32XX_CLKPWR_NAND_CLK_CTRL);
486
487         /* Setup LCD muxing to RGB565 */
488         tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
489                 ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
490                                 LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
491         tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
492         __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
493
494         /* Set up I2C pull levels */
495         tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
496         tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
497                 LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
498         __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
499
500         /* Initalise Serial device */
501         lpc32xx_serial_init();
502
503         /*
504          * AMBA peripheral clocks need to be enabled prior to AMBA device
505          * detection or a data fault will occur, so enable the clocks
506          * here. However, we don't want to enable them if the peripheral
507          * isn't included in the image
508          */
509         /* Initialise SSP clock */
510         tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
511         __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
512                         LPC32XX_CLKPWR_SSP_CLK_CTRL);
513
514         /* Initialise LCD clock */
515         tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
516         __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
517                         LPC32XX_CLKPWR_LCDCLK_CTRL);
518
519         /* Enable SD card clock so AMBA driver will work correctly. The
520            AMBA driver needs the clock before the SD card controller
521            driver initializes it. The clock will turn off once the driver
522            has been initialized. */
523         tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
524         tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
525                 LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
526         __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
527
528         /* Disable UART5->USB transparent mode or USB won't work */
529         tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
530         tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB;
531         __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
532
533         /* Add platform devcies */
534         platform_add_devices(fdi3250_devs, ARRAY_SIZE(fdi3250_devs));
535 }
536
537 static int __init lpc32xx_display_uid(void)
538 {
539         u32 uid[4];
540
541         lpc32xx_get_uid(uid);
542
543         printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
544                         uid[3], uid[2], uid[1], uid[0]);
545
546         return 1;
547 }
548 arch_initcall(lpc32xx_display_uid);
549
550 MACHINE_START (FDI3250, "Future Designs board with the LPC3250 Microcontroller")
551         .phys_io        = LPC32XX_UART5_BASE,
552         .io_pg_offst    = ((IO_ADDRESS(LPC32XX_HS_UART1_BASE))>>18) & 0xfffc,
553         .boot_params    = 0x80000100,
554         .map_io         = lpc32xx_map_io,
555         .init_irq       = lpc32xx_init_irq,
556         .timer          = &lpc32xx_timer,
557         .init_machine   = fdi3250_board_init,
558         MACHINE_END
559
560 /* For backwards compatibility with older bootloaders only */
561 MACHINE_START (LPC3XXX, "Future Designs board with the LPC3250 Microcontroller")
562         .phys_io        = LPC32XX_UART5_BASE,
563         .io_pg_offst    = ((IO_ADDRESS(LPC32XX_HS_UART1_BASE))>>18) & 0xfffc,
564         .boot_params    = 0x80000100,
565         .map_io         = lpc32xx_map_io,
566         .init_irq       = lpc32xx_init_irq,
567         .timer          = &lpc32xx_timer,
568         .init_machine   = fdi3250_board_init,
569         MACHINE_END