Merge branch 'linus' into x86/cpu
[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         }
228 #endif
229 #ifdef CONFIG_SH_MIGOR_QVGA
230         .clock_source = LCDC_CLK_PERIPHERAL,
231         .ch[0] = {
232                 .chan = LCDC_CHAN_MAINLCD,
233                 .bpp = 16,
234                 .interface_type = SYS16A,
235                 .clock_divider = 10,
236                 .lcd_cfg = {
237                         .name = "PH240320T",
238                         .xres = 320,
239                         .yres = 240,
240                         .left_margin = 0,
241                         .right_margin = 16,
242                         .hsync_len = 8,
243                         .upper_margin = 1,
244                         .lower_margin = 17,
245                         .vsync_len = 2,
246                         .sync = FB_SYNC_HOR_HIGH_ACT,
247                 },
248                 .board_cfg = {
249                         .setup_sys = migor_lcd_qvga_setup,
250                 },
251                 .sys_bus_cfg = {
252                         .ldmt2r = 0x06000a09,
253                         .ldmt3r = 0x180e3418,
254                 },
255         }
256 #endif
257 };
258
259 static struct resource migor_lcdc_resources[] = {
260         [0] = {
261                 .name   = "LCDC",
262                 .start  = 0xfe940000, /* P4-only space */
263                 .end    = 0xfe941fff,
264                 .flags  = IORESOURCE_MEM,
265         },
266 };
267
268 static struct platform_device migor_lcdc_device = {
269         .name           = "sh_mobile_lcdc_fb",
270         .num_resources  = ARRAY_SIZE(migor_lcdc_resources),
271         .resource       = migor_lcdc_resources,
272         .dev    = {
273                 .platform_data  = &sh_mobile_lcdc_info,
274         },
275 };
276
277 static struct clk *camera_clk;
278
279 static void camera_power_on(void)
280 {
281         unsigned char value;
282
283         camera_clk = clk_get(NULL, "video_clk");
284         clk_set_rate(camera_clk, 24000000);
285         clk_enable(camera_clk); /* start VIO_CKO */
286
287         mdelay(10);
288         value = ctrl_inb(PORT_PTDR);
289         value &= ~0x09;
290 #ifndef CONFIG_SH_MIGOR_RTA_WVGA
291         value |= 0x01;
292 #endif
293         ctrl_outb(value, PORT_PTDR);
294         mdelay(10);
295
296         ctrl_outb(value | 8, PORT_PTDR);
297 }
298
299 static void camera_power_off(void)
300 {
301         clk_disable(camera_clk); /* stop VIO_CKO */
302         clk_put(camera_clk);
303
304         ctrl_outb(ctrl_inb(PORT_PTDR) & ~0x08, PORT_PTDR);
305 }
306
307 #ifdef CONFIG_I2C
308 static unsigned char camera_ov772x_magic[] =
309 {
310         0x09, 0x01, 0x0c, 0x10, 0x0d, 0x41, 0x0e, 0x01,
311         0x12, 0x00, 0x13, 0x8F, 0x14, 0x4A, 0x15, 0x00,
312         0x16, 0x00, 0x17, 0x23, 0x18, 0xa0, 0x19, 0x07,
313         0x1a, 0xf0, 0x1b, 0x40, 0x1f, 0x00, 0x20, 0x10,
314         0x22, 0xff, 0x23, 0x01, 0x28, 0x00, 0x29, 0xa0,
315         0x2a, 0x00, 0x2b, 0x00, 0x2c, 0xf0, 0x2d, 0x00,
316         0x2e, 0x00, 0x30, 0x80, 0x31, 0x60, 0x32, 0x00,
317         0x33, 0x00, 0x34, 0x00, 0x3d, 0x80, 0x3e, 0xe2,
318         0x3f, 0x1f, 0x42, 0x80, 0x43, 0x80, 0x44, 0x80,
319         0x45, 0x80, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
320         0x49, 0x50, 0x4a, 0x30, 0x4b, 0x50, 0x4c, 0x50,
321         0x4d, 0x00, 0x4e, 0xef, 0x4f, 0x10, 0x50, 0x60,
322         0x51, 0x00, 0x52, 0x00, 0x53, 0x24, 0x54, 0x7a,
323         0x55, 0xfc, 0x62, 0xff, 0x63, 0xf0, 0x64, 0x1f,
324         0x65, 0x00, 0x66, 0x10, 0x67, 0x00, 0x68, 0x00,
325         0x69, 0x5c, 0x6a, 0x11, 0x6b, 0xa2, 0x6c, 0x01,
326         0x6d, 0x50, 0x6e, 0x80, 0x6f, 0x80, 0x70, 0x0f,
327         0x71, 0x00, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x0f,
328         0x75, 0xff, 0x78, 0x10, 0x79, 0x70, 0x7a, 0x70,
329         0x7b, 0xf0, 0x7c, 0xf0, 0x7d, 0xf0, 0x7e, 0x0e,
330         0x7f, 0x1a, 0x80, 0x31, 0x81, 0x5a, 0x82, 0x69,
331         0x83, 0x75, 0x84, 0x7e, 0x85, 0x88, 0x86, 0x8f,
332         0x87, 0x96, 0x88, 0xa3, 0x89, 0xaf, 0x8a, 0xc4,
333         0x8b, 0xd7, 0x8c, 0xe8, 0x8d, 0x20, 0x8e, 0x00,
334         0x8f, 0x00, 0x90, 0x08, 0x91, 0x10, 0x92, 0x1f,
335         0x93, 0x01, 0x94, 0x2c, 0x95, 0x24, 0x96, 0x08,
336         0x97, 0x14, 0x98, 0x24, 0x99, 0x38, 0x9a, 0x9e,
337         0x9b, 0x00, 0x9c, 0x40, 0x9e, 0x11, 0x9f, 0x02,
338         0xa0, 0x00, 0xa1, 0x40, 0xa2, 0x40, 0xa3, 0x06,
339         0xa4, 0x00, 0xa6, 0x00, 0xa7, 0x40, 0xa8, 0x40,
340         0xa9, 0x80, 0xaa, 0x80, 0xab, 0x06, 0xac, 0xff,
341         0x12, 0x06, 0x64, 0x3f, 0x12, 0x46, 0x17, 0x3f,
342         0x18, 0x50, 0x19, 0x03, 0x1a, 0x78, 0x29, 0x50,
343         0x2c, 0x78,
344 };
345
346 static int ov772x_set_capture(struct soc_camera_platform_info *info,
347                               int enable)
348 {
349         struct i2c_adapter *a = i2c_get_adapter(0);
350         struct i2c_msg msg;
351         int ret = 0;
352         int i;
353
354         if (!enable)
355                 return 0; /* camera_power_off() is enough */
356
357         for (i = 0; i < ARRAY_SIZE(camera_ov772x_magic); i += 2) {
358                 u_int8_t buf[8];
359
360                 msg.addr = 0x21;
361                 msg.buf = buf;
362                 msg.len = 2;
363                 msg.flags = 0;
364
365                 buf[0] = camera_ov772x_magic[i];
366                 buf[1] = camera_ov772x_magic[i + 1];
367
368                 ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1);
369         }
370
371         return ret;
372 }
373
374 static struct soc_camera_platform_info ov772x_info = {
375         .iface = 0,
376         .format_name = "RGB565",
377         .format_depth = 16,
378         .format = {
379                 .pixelformat = V4L2_PIX_FMT_RGB565,
380                 .colorspace = V4L2_COLORSPACE_SRGB,
381                 .width = 320,
382                 .height = 240,
383         },
384         .bus_param =  SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
385         SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
386         .set_capture = ov772x_set_capture,
387 };
388
389 static struct platform_device migor_camera_device = {
390         .name           = "soc_camera_platform",
391         .dev    = {
392                 .platform_data  = &ov772x_info,
393         },
394 };
395 #endif /* CONFIG_I2C */
396
397 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
398         .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
399         | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
400         .enable_camera = camera_power_on,
401         .disable_camera = camera_power_off,
402 };
403
404 static struct resource migor_ceu_resources[] = {
405         [0] = {
406                 .name   = "CEU",
407                 .start  = 0xfe910000,
408                 .end    = 0xfe91009f,
409                 .flags  = IORESOURCE_MEM,
410         },
411         [1] = {
412                 .start  = 52,
413                 .flags  = IORESOURCE_IRQ,
414         },
415         [2] = {
416                 /* place holder for contiguous memory */
417         },
418 };
419
420 static struct platform_device migor_ceu_device = {
421         .name           = "sh_mobile_ceu",
422         .num_resources  = ARRAY_SIZE(migor_ceu_resources),
423         .resource       = migor_ceu_resources,
424         .dev    = {
425                 .platform_data  = &sh_mobile_ceu_info,
426         },
427 };
428
429 static struct platform_device *migor_devices[] __initdata = {
430         &smc91x_eth_device,
431         &sh_keysc_device,
432         &migor_lcdc_device,
433         &migor_ceu_device,
434 #ifdef CONFIG_I2C
435         &migor_camera_device,
436 #endif
437         &migor_nor_flash_device,
438         &migor_nand_flash_device,
439 };
440
441 static struct i2c_board_info migor_i2c_devices[] = {
442         {
443                 I2C_BOARD_INFO("rs5c372b", 0x32),
444         },
445         {
446                 I2C_BOARD_INFO("migor_ts", 0x51),
447                 .irq = 38, /* IRQ6 */
448         },
449 };
450
451 static int __init migor_devices_setup(void)
452 {
453         clk_always_enable("mstp214"); /* KEYSC */
454         clk_always_enable("mstp200"); /* LCDC */
455         clk_always_enable("mstp203"); /* CEU */
456
457         platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
458
459         i2c_register_board_info(0, migor_i2c_devices,
460                                 ARRAY_SIZE(migor_i2c_devices));
461  
462         return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
463 }
464 __initcall(migor_devices_setup);
465
466 static void __init migor_setup(char **cmdline_p)
467 {
468         /* SMC91C111 - Enable IRQ0 */
469         ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR);
470
471         /* KEYSC */
472         ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR);
473         ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR);
474         ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
475         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
476         ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
477
478         /* NAND Flash */
479         ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
480         ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
481                   BSC_CS6ABCR);
482
483         /* Touch Panel - Enable IRQ6 */
484         ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
485         ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
486         ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
487
488 #ifdef CONFIG_SH_MIGOR_RTA_WVGA
489         /* LCDC - WVGA - Enable RGB Interface signals */
490         ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
491         ctrl_outw(0x0000, PORT_PHCR);
492         ctrl_outw(0x0000, PORT_PLCR);
493         ctrl_outw(0x0000, PORT_PMCR);
494         ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR);
495         ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD);
496         ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB);
497         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
498 #endif
499 #ifdef CONFIG_SH_MIGOR_QVGA
500         /* LCDC - QVGA - Enable SYS Interface signals */
501         ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
502         ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR);
503         ctrl_outw(0x0000, PORT_PLCR);
504         ctrl_outw(0x0000, PORT_PMCR);
505         ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR);
506         ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD);
507         ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB);
508         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
509 #endif
510
511         /* CEU */
512         ctrl_outw((ctrl_inw(PORT_PTCR) & ~0x03c3) | 0x0051, PORT_PTCR);
513         ctrl_outw(ctrl_inw(PORT_PUCR) & ~0x03ff, PORT_PUCR);
514         ctrl_outw(ctrl_inw(PORT_PVCR) & ~0x03ff, PORT_PVCR);
515         ctrl_outw(ctrl_inw(PORT_PWCR) & ~0x3c00, PORT_PWCR);
516         ctrl_outw(ctrl_inw(PORT_PSELC) | 0x0001, PORT_PSELC);
517         ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x2000, PORT_PSELD);
518         ctrl_outw(ctrl_inw(PORT_PSELE) | 0x000f, PORT_PSELE);
519         ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2200, PORT_MSELCRB);
520         ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x0a00, PORT_HIZCRA);
521         ctrl_outw(ctrl_inw(PORT_HIZCRB) & ~0x0003, PORT_HIZCRB);
522 }
523
524 static struct sh_machine_vector mv_migor __initmv = {
525         .mv_name                = "Migo-R",
526         .mv_setup               = migor_setup,
527 };