Merge commit 'v2.6.27-rc6' into timers/hpet
[linux-2.6] / arch / sh / boards / mach-migor / setup.c
1 /*
2  * Renesas System Solutions Asia Pte. Ltd - Migo-R
3  *
4  * Copyright (C) 2008 Magnus Damm
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  */
10 #include <linux/init.h>
11 #include <linux/platform_device.h>
12 #include <linux/interrupt.h>
13 #include <linux/input.h>
14 #include <linux/mtd/physmap.h>
15 #include <linux/mtd/nand.h>
16 #include <linux/i2c.h>
17 #include <linux/smc91x.h>
18 #include <linux/delay.h>
19 #include <linux/clk.h>
20 #include <media/soc_camera_platform.h>
21 #include <media/sh_mobile_ceu.h>
22 #include <asm/clock.h>
23 #include <asm/machvec.h>
24 #include <asm/io.h>
25 #include <asm/sh_keysc.h>
26 #include <asm/sh_mobile_lcdc.h>
27 #include <asm/migor.h>
28
29 /* Address     IRQ  Size  Bus  Description
30  * 0x00000000       64MB  16   NOR Flash (SP29PL256N)
31  * 0x0c000000       64MB  64   SDRAM (2xK4M563233G)
32  * 0x10000000  IRQ0       16   Ethernet (SMC91C111)
33  * 0x14000000  IRQ4       16   USB 2.0 Host Controller (M66596)
34  * 0x18000000       8GB    8   NAND Flash (K9K8G08U0A)
35  */
36
37 static struct smc91x_platdata smc91x_info = {
38         .flags = SMC91X_USE_16BIT,
39 };
40
41 static struct resource smc91x_eth_resources[] = {
42         [0] = {
43                 .name   = "SMC91C111" ,
44                 .start  = 0x10000300,
45                 .end    = 0x1000030f,
46                 .flags  = IORESOURCE_MEM,
47         },
48         [1] = {
49                 .start  = 32, /* IRQ0 */
50                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
51         },
52 };
53
54 static struct platform_device smc91x_eth_device = {
55         .name           = "smc91x",
56         .num_resources  = ARRAY_SIZE(smc91x_eth_resources),
57         .resource       = smc91x_eth_resources,
58         .dev    = {
59                 .platform_data  = &smc91x_info,
60         },
61 };
62
63 static struct sh_keysc_info sh_keysc_info = {
64         .mode = SH_KEYSC_MODE_2, /* KEYOUT0->4, KEYIN1->5 */
65         .scan_timing = 3,
66         .delay = 5,
67         .keycodes = {
68                 0, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER,
69                 0, KEY_F, KEY_C, KEY_D, KEY_H, KEY_1,
70                 0, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
71                 0, KEY_7, KEY_8, KEY_9, KEY_S, KEY_0,
72                 0, KEY_P, KEY_STOP, KEY_REWIND, KEY_PLAY, KEY_FASTFORWARD,
73         },
74 };
75
76 static struct resource sh_keysc_resources[] = {
77         [0] = {
78                 .start  = 0x044b0000,
79                 .end    = 0x044b000f,
80                 .flags  = IORESOURCE_MEM,
81         },
82         [1] = {
83                 .start  = 79,
84                 .flags  = IORESOURCE_IRQ,
85         },
86 };
87
88 static struct platform_device sh_keysc_device = {
89         .name           = "sh_keysc",
90         .num_resources  = ARRAY_SIZE(sh_keysc_resources),
91         .resource       = sh_keysc_resources,
92         .dev    = {
93                 .platform_data  = &sh_keysc_info,
94         },
95 };
96
97 static struct mtd_partition migor_nor_flash_partitions[] =
98 {
99         {
100                 .name = "uboot",
101                 .offset = 0,
102                 .size = (1 * 1024 * 1024),
103                 .mask_flags = MTD_WRITEABLE,    /* Read-only */
104         },
105         {
106                 .name = "rootfs",
107                 .offset = MTDPART_OFS_APPEND,
108                 .size = (15 * 1024 * 1024),
109         },
110         {
111                 .name = "other",
112                 .offset = MTDPART_OFS_APPEND,
113                 .size = MTDPART_SIZ_FULL,
114         },
115 };
116
117 static struct physmap_flash_data migor_nor_flash_data = {
118         .width          = 2,
119         .parts          = migor_nor_flash_partitions,
120         .nr_parts       = ARRAY_SIZE(migor_nor_flash_partitions),
121 };
122
123 static struct resource migor_nor_flash_resources[] = {
124         [0] = {
125                 .name           = "NOR Flash",
126                 .start          = 0x00000000,
127                 .end            = 0x03ffffff,
128                 .flags          = IORESOURCE_MEM,
129         }
130 };
131
132 static struct platform_device migor_nor_flash_device = {
133         .name           = "physmap-flash",
134         .resource       = migor_nor_flash_resources,
135         .num_resources  = ARRAY_SIZE(migor_nor_flash_resources),
136         .dev            = {
137                 .platform_data = &migor_nor_flash_data,
138         },
139 };
140
141 static struct mtd_partition migor_nand_flash_partitions[] = {
142         {
143                 .name           = "nanddata1",
144                 .offset         = 0x0,
145                 .size           = 512 * 1024 * 1024,
146         },
147         {
148                 .name           = "nanddata2",
149                 .offset         = MTDPART_OFS_APPEND,
150                 .size           = 512 * 1024 * 1024,
151         },
152 };
153
154 static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
155                                      unsigned int ctrl)
156 {
157         struct nand_chip *chip = mtd->priv;
158
159         if (cmd == NAND_CMD_NONE)
160                 return;
161
162         if (ctrl & NAND_CLE)
163                 writeb(cmd, chip->IO_ADDR_W + 0x00400000);
164         else if (ctrl & NAND_ALE)
165                 writeb(cmd, chip->IO_ADDR_W + 0x00800000);
166         else
167                 writeb(cmd, chip->IO_ADDR_W);
168 }
169
170 static int migor_nand_flash_ready(struct mtd_info *mtd)
171 {
172         return ctrl_inb(PORT_PADR) & 0x02; /* PTA1 */
173 }
174
175 struct platform_nand_data migor_nand_flash_data = {
176         .chip = {
177                 .nr_chips = 1,
178                 .partitions = migor_nand_flash_partitions,
179                 .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions),
180                 .chip_delay = 20,
181                 .part_probe_types = (const char *[]) { "cmdlinepart", NULL },
182         },
183         .ctrl = {
184                 .dev_ready = migor_nand_flash_ready,
185                 .cmd_ctrl = migor_nand_flash_cmd_ctl,
186         },
187 };
188
189 static struct resource migor_nand_flash_resources[] = {
190         [0] = {
191                 .name           = "NAND Flash",
192                 .start          = 0x18000000,
193                 .end            = 0x18ffffff,
194                 .flags          = IORESOURCE_MEM,
195         },
196 };
197
198 static struct platform_device migor_nand_flash_device = {
199         .name           = "gen_nand",
200         .resource       = migor_nand_flash_resources,
201         .num_resources  = ARRAY_SIZE(migor_nand_flash_resources),
202         .dev            = {
203                 .platform_data = &migor_nand_flash_data,
204         }
205 };
206
207 static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
208 #ifdef CONFIG_SH_MIGOR_RTA_WVGA
209         .clock_source = LCDC_CLK_BUS,
210         .ch[0] = {
211                 .chan = LCDC_CHAN_MAINLCD,
212                 .bpp = 16,
213                 .interface_type = RGB16,
214                 .clock_divider = 2,
215                 .lcd_cfg = {
216                         .name = "LB070WV1",
217                         .xres = 800,
218                         .yres = 480,
219                         .left_margin = 64,
220                         .right_margin = 16,
221                         .hsync_len = 120,
222                         .upper_margin = 1,
223                         .lower_margin = 17,
224                         .vsync_len = 2,
225                         .sync = 0,
226                 },
227                 .lcd_size_cfg = { /* 7.0 inch */
228                         .width = 152,
229                         .height = 91,
230                 },
231         }
232 #endif
233 #ifdef CONFIG_SH_MIGOR_QVGA
234         .clock_source = LCDC_CLK_PERIPHERAL,
235         .ch[0] = {
236                 .chan = LCDC_CHAN_MAINLCD,
237                 .bpp = 16,
238                 .interface_type = SYS16A,
239                 .clock_divider = 10,
240                 .lcd_cfg = {
241                         .name = "PH240320T",
242                         .xres = 320,
243                         .yres = 240,
244                         .left_margin = 0,
245                         .right_margin = 16,
246                         .hsync_len = 8,
247                         .upper_margin = 1,
248                         .lower_margin = 17,
249                         .vsync_len = 2,
250                         .sync = FB_SYNC_HOR_HIGH_ACT,
251                 },
252                 .lcd_size_cfg = { /* 2.4 inch */
253                         .width = 49,
254                         .height = 37,
255                 },
256                 .board_cfg = {
257                         .setup_sys = migor_lcd_qvga_setup,
258                 },
259                 .sys_bus_cfg = {
260                         .ldmt2r = 0x06000a09,
261                         .ldmt3r = 0x180e3418,
262                 },
263         }
264 #endif
265 };
266
267 static struct resource migor_lcdc_resources[] = {
268         [0] = {
269                 .name   = "LCDC",
270                 .start  = 0xfe940000, /* P4-only space */
271                 .end    = 0xfe941fff,
272                 .flags  = IORESOURCE_MEM,
273         },
274 };
275
276 static struct platform_device migor_lcdc_device = {
277         .name           = "sh_mobile_lcdc_fb",
278         .num_resources  = ARRAY_SIZE(migor_lcdc_resources),
279         .resource       = migor_lcdc_resources,
280         .dev    = {
281                 .platform_data  = &sh_mobile_lcdc_info,
282         },
283 };
284
285 static struct clk *camera_clk;
286
287 static void camera_power_on(void)
288 {
289         unsigned char value;
290
291         camera_clk = clk_get(NULL, "video_clk");
292         clk_set_rate(camera_clk, 24000000);
293         clk_enable(camera_clk); /* start VIO_CKO */
294
295         mdelay(10);
296         value = ctrl_inb(PORT_PTDR);
297         value &= ~0x09;
298 #ifndef CONFIG_SH_MIGOR_RTA_WVGA
299         value |= 0x01;
300 #endif
301         ctrl_outb(value, PORT_PTDR);
302         mdelay(10);
303
304         ctrl_outb(value | 8, PORT_PTDR);
305 }
306
307 static void camera_power_off(void)
308 {
309         clk_disable(camera_clk); /* stop VIO_CKO */
310         clk_put(camera_clk);
311
312         ctrl_outb(ctrl_inb(PORT_PTDR) & ~0x08, PORT_PTDR);
313 }
314
315 #ifdef CONFIG_I2C
316 static unsigned char camera_ov772x_magic[] =
317 {
318         0x09, 0x01, 0x0c, 0x10, 0x0d, 0x41, 0x0e, 0x01,
319         0x12, 0x00, 0x13, 0x8F, 0x14, 0x4A, 0x15, 0x00,
320         0x16, 0x00, 0x17, 0x23, 0x18, 0xa0, 0x19, 0x07,
321         0x1a, 0xf0, 0x1b, 0x40, 0x1f, 0x00, 0x20, 0x10,
322         0x22, 0xff, 0x23, 0x01, 0x28, 0x00, 0x29, 0xa0,
323         0x2a, 0x00, 0x2b, 0x00, 0x2c, 0xf0, 0x2d, 0x00,
324         0x2e, 0x00, 0x30, 0x80, 0x31, 0x60, 0x32, 0x00,
325         0x33, 0x00, 0x34, 0x00, 0x3d, 0x80, 0x3e, 0xe2,
326         0x3f, 0x1f, 0x42, 0x80, 0x43, 0x80, 0x44, 0x80,
327         0x45, 0x80, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
328         0x49, 0x50, 0x4a, 0x30, 0x4b, 0x50, 0x4c, 0x50,
329         0x4d, 0x00, 0x4e, 0xef, 0x4f, 0x10, 0x50, 0x60,
330         0x51, 0x00, 0x52, 0x00, 0x53, 0x24, 0x54, 0x7a,
331         0x55, 0xfc, 0x62, 0xff, 0x63, 0xf0, 0x64, 0x1f,
332         0x65, 0x00, 0x66, 0x10, 0x67, 0x00, 0x68, 0x00,
333         0x69, 0x5c, 0x6a, 0x11, 0x6b, 0xa2, 0x6c, 0x01,
334         0x6d, 0x50, 0x6e, 0x80, 0x6f, 0x80, 0x70, 0x0f,
335         0x71, 0x00, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x0f,
336         0x75, 0xff, 0x78, 0x10, 0x79, 0x70, 0x7a, 0x70,
337         0x7b, 0xf0, 0x7c, 0xf0, 0x7d, 0xf0, 0x7e, 0x0e,
338         0x7f, 0x1a, 0x80, 0x31, 0x81, 0x5a, 0x82, 0x69,
339         0x83, 0x75, 0x84, 0x7e, 0x85, 0x88, 0x86, 0x8f,
340         0x87, 0x96, 0x88, 0xa3, 0x89, 0xaf, 0x8a, 0xc4,
341         0x8b, 0xd7, 0x8c, 0xe8, 0x8d, 0x20, 0x8e, 0x00,
342         0x8f, 0x00, 0x90, 0x08, 0x91, 0x10, 0x92, 0x1f,
343         0x93, 0x01, 0x94, 0x2c, 0x95, 0x24, 0x96, 0x08,
344         0x97, 0x14, 0x98, 0x24, 0x99, 0x38, 0x9a, 0x9e,
345         0x9b, 0x00, 0x9c, 0x40, 0x9e, 0x11, 0x9f, 0x02,
346         0xa0, 0x00, 0xa1, 0x40, 0xa2, 0x40, 0xa3, 0x06,
347         0xa4, 0x00, 0xa6, 0x00, 0xa7, 0x40, 0xa8, 0x40,
348         0xa9, 0x80, 0xaa, 0x80, 0xab, 0x06, 0xac, 0xff,
349         0x12, 0x06, 0x64, 0x3f, 0x12, 0x46, 0x17, 0x3f,
350         0x18, 0x50, 0x19, 0x03, 0x1a, 0x78, 0x29, 0x50,
351         0x2c, 0x78,
352 };
353
354 static int ov772x_set_capture(struct soc_camera_platform_info *info,
355                               int enable)
356 {
357         struct i2c_adapter *a = i2c_get_adapter(0);
358         struct i2c_msg msg;
359         int ret = 0;
360         int i;
361
362         if (!enable)
363                 return 0; /* camera_power_off() is enough */
364
365         for (i = 0; i < ARRAY_SIZE(camera_ov772x_magic); i += 2) {
366                 u_int8_t buf[8];
367
368                 msg.addr = 0x21;
369                 msg.buf = buf;
370                 msg.len = 2;
371                 msg.flags = 0;
372
373                 buf[0] = camera_ov772x_magic[i];
374                 buf[1] = camera_ov772x_magic[i + 1];
375
376                 ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1);
377         }
378
379         return ret;
380 }
381
382 static struct soc_camera_platform_info ov772x_info = {
383         .iface = 0,
384         .format_name = "RGB565",
385         .format_depth = 16,
386         .format = {
387                 .pixelformat = V4L2_PIX_FMT_RGB565,
388                 .colorspace = V4L2_COLORSPACE_SRGB,
389                 .width = 320,
390                 .height = 240,
391         },
392         .bus_param =  SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
393         SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
394         .set_capture = ov772x_set_capture,
395 };
396
397 static struct platform_device migor_camera_device = {
398         .name           = "soc_camera_platform",
399         .dev    = {
400                 .platform_data  = &ov772x_info,
401         },
402 };
403 #endif /* CONFIG_I2C */
404
405 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
406         .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
407         | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
408         .enable_camera = camera_power_on,
409         .disable_camera = camera_power_off,
410 };
411
412 static struct resource migor_ceu_resources[] = {
413         [0] = {
414                 .name   = "CEU",
415                 .start  = 0xfe910000,
416                 .end    = 0xfe91009f,
417                 .flags  = IORESOURCE_MEM,
418         },
419         [1] = {
420                 .start  = 52,
421                 .flags  = IORESOURCE_IRQ,
422         },
423         [2] = {
424                 /* place holder for contiguous memory */
425         },
426 };
427
428 static struct platform_device migor_ceu_device = {
429         .name           = "sh_mobile_ceu",
430         .num_resources  = ARRAY_SIZE(migor_ceu_resources),
431         .resource       = migor_ceu_resources,
432         .dev    = {
433                 .platform_data  = &sh_mobile_ceu_info,
434         },
435 };
436
437 static struct platform_device *migor_devices[] __initdata = {
438         &smc91x_eth_device,
439         &sh_keysc_device,
440         &migor_lcdc_device,
441         &migor_ceu_device,
442 #ifdef CONFIG_I2C
443         &migor_camera_device,
444 #endif
445         &migor_nor_flash_device,
446         &migor_nand_flash_device,
447 };
448
449 static struct i2c_board_info migor_i2c_devices[] = {
450         {
451                 I2C_BOARD_INFO("rs5c372b", 0x32),
452         },
453         {
454                 I2C_BOARD_INFO("migor_ts", 0x51),
455                 .irq = 38, /* IRQ6 */
456         },
457 };
458
459 static int __init migor_devices_setup(void)
460 {
461         clk_always_enable("mstp214"); /* KEYSC */
462         clk_always_enable("mstp200"); /* LCDC */
463         clk_always_enable("mstp203"); /* CEU */
464
465         platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
466
467         i2c_register_board_info(0, migor_i2c_devices,
468                                 ARRAY_SIZE(migor_i2c_devices));
469  
470         return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
471 }
472 __initcall(migor_devices_setup);
473
474 static void __init migor_setup(char **cmdline_p)
475 {
476         /* SMC91C111 - Enable IRQ0 */
477         ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR);
478
479         /* KEYSC */
480         ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR);
481         ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR);
482         ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
483         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
484         ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
485
486         /* NAND Flash */
487         ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
488         ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
489                   BSC_CS6ABCR);
490
491         /* Touch Panel - Enable IRQ6 */
492         ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
493         ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
494         ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
495
496 #ifdef CONFIG_SH_MIGOR_RTA_WVGA
497         /* LCDC - WVGA - Enable RGB Interface signals */
498         ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
499         ctrl_outw(0x0000, PORT_PHCR);
500         ctrl_outw(0x0000, PORT_PLCR);
501         ctrl_outw(0x0000, PORT_PMCR);
502         ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR);
503         ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD);
504         ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB);
505         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
506 #endif
507 #ifdef CONFIG_SH_MIGOR_QVGA
508         /* LCDC - QVGA - Enable SYS Interface signals */
509         ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
510         ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR);
511         ctrl_outw(0x0000, PORT_PLCR);
512         ctrl_outw(0x0000, PORT_PMCR);
513         ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR);
514         ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD);
515         ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB);
516         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
517 #endif
518
519         /* CEU */
520         ctrl_outw((ctrl_inw(PORT_PTCR) & ~0x03c3) | 0x0051, PORT_PTCR);
521         ctrl_outw(ctrl_inw(PORT_PUCR) & ~0x03ff, PORT_PUCR);
522         ctrl_outw(ctrl_inw(PORT_PVCR) & ~0x03ff, PORT_PVCR);
523         ctrl_outw(ctrl_inw(PORT_PWCR) & ~0x3c00, PORT_PWCR);
524         ctrl_outw(ctrl_inw(PORT_PSELC) | 0x0001, PORT_PSELC);
525         ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x2000, PORT_PSELD);
526         ctrl_outw(ctrl_inw(PORT_PSELE) | 0x000f, PORT_PSELE);
527         ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2200, PORT_MSELCRB);
528         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x0a00, PORT_HIZCRA);
529         ctrl_outw(ctrl_inw(PORT_HIZCRB) & ~0x0003, PORT_HIZCRB);
530 }
531
532 static struct sh_machine_vector mv_migor __initmv = {
533         .mv_name                = "Migo-R",
534         .mv_setup               = migor_setup,
535 };