Merge http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm into...
[linux-2.6.git] / arch / arm / mach-s3c2440 / mach-anubis.c
1 /* linux/arch/arm/mach-s3c2440/mach-anubis.c
2  *
3  * Copyright (c) 2003-2005,2008 Simtec Electronics
4  *      http://armlinux.simtec.co.uk/
5  *      Ben Dooks <ben@simtec.co.uk>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10 */
11
12 #include <linux/kernel.h>
13 #include <linux/types.h>
14 #include <linux/interrupt.h>
15 #include <linux/list.h>
16 #include <linux/timer.h>
17 #include <linux/init.h>
18 #include <linux/serial_core.h>
19 #include <linux/platform_device.h>
20 #include <linux/ata_platform.h>
21 #include <linux/i2c.h>
22
23 #include <linux/sm501.h>
24 #include <linux/sm501-regs.h>
25
26 #include <asm/mach/arch.h>
27 #include <asm/mach/map.h>
28 #include <asm/mach/irq.h>
29
30 #include <mach/anubis-map.h>
31 #include <mach/anubis-irq.h>
32 #include <mach/anubis-cpld.h>
33
34 #include <mach/hardware.h>
35 #include <asm/io.h>
36 #include <asm/irq.h>
37 #include <asm/mach-types.h>
38
39 #include <asm/plat-s3c/regs-serial.h>
40 #include <mach/regs-gpio.h>
41 #include <mach/regs-mem.h>
42 #include <mach/regs-lcd.h>
43 #include <asm/plat-s3c/nand.h>
44
45 #include <linux/mtd/mtd.h>
46 #include <linux/mtd/nand.h>
47 #include <linux/mtd/nand_ecc.h>
48 #include <linux/mtd/partitions.h>
49
50 #include <net/ax88796.h>
51
52 #include <asm/plat-s3c24xx/clock.h>
53 #include <asm/plat-s3c24xx/devs.h>
54 #include <asm/plat-s3c24xx/cpu.h>
55
56 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
57
58 static struct map_desc anubis_iodesc[] __initdata = {
59   /* ISA IO areas */
60
61   {
62         .virtual        = (u32)S3C24XX_VA_ISA_BYTE,
63         .pfn            = __phys_to_pfn(0x0),
64         .length         = SZ_4M,
65         .type           = MT_DEVICE,
66   }, {
67         .virtual        = (u32)S3C24XX_VA_ISA_WORD,
68         .pfn            = __phys_to_pfn(0x0),
69         .length         = SZ_4M,
70         .type           = MT_DEVICE,
71   },
72
73   /* we could possibly compress the next set down into a set of smaller tables
74    * pagetables, but that would mean using an L2 section, and it still means
75    * we cannot actually feed the same register to an LDR due to 16K spacing
76    */
77
78   /* CPLD control registers */
79
80   {
81         .virtual        = (u32)ANUBIS_VA_CTRL1,
82         .pfn            = __phys_to_pfn(ANUBIS_PA_CTRL1),
83         .length         = SZ_4K,
84         .type           = MT_DEVICE,
85   }, {
86         .virtual        = (u32)ANUBIS_VA_IDREG,
87         .pfn            = __phys_to_pfn(ANUBIS_PA_IDREG),
88         .length         = SZ_4K,
89         .type           = MT_DEVICE,
90   },
91 };
92
93 #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
94 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
95 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
96
97 static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
98         [0] = {
99                 .name           = "uclk",
100                 .divisor        = 1,
101                 .min_baud       = 0,
102                 .max_baud       = 0,
103         },
104         [1] = {
105                 .name           = "pclk",
106                 .divisor        = 1,
107                 .min_baud       = 0,
108                 .max_baud       = 0,
109         }
110 };
111
112
113 static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
114         [0] = {
115                 .hwport      = 0,
116                 .flags       = 0,
117                 .ucon        = UCON,
118                 .ulcon       = ULCON,
119                 .ufcon       = UFCON,
120                 .clocks      = anubis_serial_clocks,
121                 .clocks_size = ARRAY_SIZE(anubis_serial_clocks),
122         },
123         [1] = {
124                 .hwport      = 2,
125                 .flags       = 0,
126                 .ucon        = UCON,
127                 .ulcon       = ULCON,
128                 .ufcon       = UFCON,
129                 .clocks      = anubis_serial_clocks,
130                 .clocks_size = ARRAY_SIZE(anubis_serial_clocks),
131         },
132 };
133
134 /* NAND Flash on Anubis board */
135
136 static int external_map[]   = { 2 };
137 static int chip0_map[]      = { 0 };
138 static int chip1_map[]      = { 1 };
139
140 static struct mtd_partition anubis_default_nand_part[] = {
141         [0] = {
142                 .name   = "Boot Agent",
143                 .size   = SZ_16K,
144                 .offset = 0,
145         },
146         [1] = {
147                 .name   = "/boot",
148                 .size   = SZ_4M - SZ_16K,
149                 .offset = SZ_16K,
150         },
151         [2] = {
152                 .name   = "user1",
153                 .offset = SZ_4M,
154                 .size   = SZ_32M - SZ_4M,
155         },
156         [3] = {
157                 .name   = "user2",
158                 .offset = SZ_32M,
159                 .size   = MTDPART_SIZ_FULL,
160         }
161 };
162
163 static struct mtd_partition anubis_default_nand_part_large[] = {
164         [0] = {
165                 .name   = "Boot Agent",
166                 .size   = SZ_128K,
167                 .offset = 0,
168         },
169         [1] = {
170                 .name   = "/boot",
171                 .size   = SZ_4M - SZ_128K,
172                 .offset = SZ_128K,
173         },
174         [2] = {
175                 .name   = "user1",
176                 .offset = SZ_4M,
177                 .size   = SZ_32M - SZ_4M,
178         },
179         [3] = {
180                 .name   = "user2",
181                 .offset = SZ_32M,
182                 .size   = MTDPART_SIZ_FULL,
183         }
184 };
185
186 /* the Anubis has 3 selectable slots for nand-flash, the two
187  * on-board chip areas, as well as the external slot.
188  *
189  * Note, there is no current hot-plug support for the External
190  * socket.
191 */
192
193 static struct s3c2410_nand_set anubis_nand_sets[] = {
194         [1] = {
195                 .name           = "External",
196                 .nr_chips       = 1,
197                 .nr_map         = external_map,
198                 .nr_partitions  = ARRAY_SIZE(anubis_default_nand_part),
199                 .partitions     = anubis_default_nand_part,
200         },
201         [0] = {
202                 .name           = "chip0",
203                 .nr_chips       = 1,
204                 .nr_map         = chip0_map,
205                 .nr_partitions  = ARRAY_SIZE(anubis_default_nand_part),
206                 .partitions     = anubis_default_nand_part,
207         },
208         [2] = {
209                 .name           = "chip1",
210                 .nr_chips       = 1,
211                 .nr_map         = chip1_map,
212                 .nr_partitions  = ARRAY_SIZE(anubis_default_nand_part),
213                 .partitions     = anubis_default_nand_part,
214         },
215 };
216
217 static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
218 {
219         unsigned int tmp;
220
221         slot = set->nr_map[slot] & 3;
222
223         pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
224                  slot, set, set->nr_map);
225
226         tmp = __raw_readb(ANUBIS_VA_CTRL1);
227         tmp &= ~ANUBIS_CTRL1_NANDSEL;
228         tmp |= slot;
229
230         pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
231
232         __raw_writeb(tmp, ANUBIS_VA_CTRL1);
233 }
234
235 static struct s3c2410_platform_nand anubis_nand_info = {
236         .tacls          = 25,
237         .twrph0         = 55,
238         .twrph1         = 40,
239         .nr_sets        = ARRAY_SIZE(anubis_nand_sets),
240         .sets           = anubis_nand_sets,
241         .select_chip    = anubis_nand_select,
242 };
243
244 /* IDE channels */
245
246 struct pata_platform_info anubis_ide_platdata = {
247         .ioport_shift   = 5,
248 };
249
250 static struct resource anubis_ide0_resource[] = {
251         {
252                 .start  = S3C2410_CS3,
253                 .end    = S3C2410_CS3 + (8*32) - 1,
254                 .flags  = IORESOURCE_MEM,
255         }, {
256                 .start  = S3C2410_CS3 + (1<<26) + (6*32),
257                 .end    = S3C2410_CS3 + (1<<26) + (7*32) - 1,
258                 .flags  = IORESOURCE_MEM,
259         }, {
260                 .start  = IRQ_IDE0,
261                 .end    = IRQ_IDE0,
262                 .flags  = IORESOURCE_IRQ,
263         },
264 };
265
266 static struct platform_device anubis_device_ide0 = {
267         .name           = "pata_platform",
268         .id             = 0,
269         .num_resources  = ARRAY_SIZE(anubis_ide0_resource),
270         .resource       = anubis_ide0_resource,
271         .dev    = {
272                 .platform_data = &anubis_ide_platdata,
273                 .coherent_dma_mask = ~0,
274         },
275 };
276
277 static struct resource anubis_ide1_resource[] = {
278         {
279                 .start  = S3C2410_CS4,
280                 .end    = S3C2410_CS4 + (8*32) - 1,
281                 .flags  = IORESOURCE_MEM,
282         }, {
283                 .start  = S3C2410_CS4 + (1<<26) + (6*32),
284                 .end    = S3C2410_CS4 + (1<<26) + (7*32) - 1,
285                 .flags  = IORESOURCE_MEM,
286         }, {
287                 .start  = IRQ_IDE0,
288                 .end    = IRQ_IDE0,
289                 .flags  = IORESOURCE_IRQ,
290         },
291 };
292
293 static struct platform_device anubis_device_ide1 = {
294         .name           = "pata_platform",
295         .id             = 1,
296         .num_resources  = ARRAY_SIZE(anubis_ide1_resource),
297         .resource       = anubis_ide1_resource,
298         .dev    = {
299                 .platform_data = &anubis_ide_platdata,
300                 .coherent_dma_mask = ~0,
301         },
302 };
303
304 /* Asix AX88796 10/100 ethernet controller */
305
306 static struct ax_plat_data anubis_asix_platdata = {
307         .flags          = AXFLG_MAC_FROMDEV,
308         .wordlength     = 2,
309         .dcr_val        = 0x48,
310         .rcr_val        = 0x40,
311 };
312
313 static struct resource anubis_asix_resource[] = {
314         [0] = {
315                 .start = S3C2410_CS5,
316                 .end   = S3C2410_CS5 + (0x20 * 0x20) -1,
317                 .flags = IORESOURCE_MEM
318         },
319         [1] = {
320                 .start = IRQ_ASIX,
321                 .end   = IRQ_ASIX,
322                 .flags = IORESOURCE_IRQ
323         }
324 };
325
326 static struct platform_device anubis_device_asix = {
327         .name           = "ax88796",
328         .id             = 0,
329         .num_resources  = ARRAY_SIZE(anubis_asix_resource),
330         .resource       = anubis_asix_resource,
331         .dev            = {
332                 .platform_data = &anubis_asix_platdata,
333         }
334 };
335
336 /* SM501 */
337
338 static struct resource anubis_sm501_resource[] = {
339         [0] = {
340                 .start  = S3C2410_CS2,
341                 .end    = S3C2410_CS2 + SZ_8M,
342                 .flags  = IORESOURCE_MEM,
343         },
344         [1] = {
345                 .start  = S3C2410_CS2 + SZ_64M - SZ_2M,
346                 .end    = S3C2410_CS2 + SZ_64M - 1,
347                 .flags  = IORESOURCE_MEM,
348         },
349         [2] = {
350                 .start  = IRQ_EINT0,
351                 .end    = IRQ_EINT0,
352                 .flags  = IORESOURCE_IRQ,
353         },
354 };
355
356 static struct sm501_initdata anubis_sm501_initdata = {
357         .gpio_high      = {
358                 .set    = 0x3F000000,           /* 24bit panel */
359                 .mask   = 0x0,
360         },
361         .misc_timing    = {
362                 .set    = 0x010100,             /* SDRAM timing */
363                 .mask   = 0x1F1F00,
364         },
365         .misc_control   = {
366                 .set    = SM501_MISC_PNL_24BIT,
367                 .mask   = 0,
368         },
369
370         /* set the SDRAM and bus clocks */
371         .mclk           = 72 * MHZ,
372         .m1xclk         = 144 * MHZ,
373 };
374
375 static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
376         [0] = {
377                 .pin_scl        = 44,
378                 .pin_sda        = 45,
379         },
380         [1] = {
381                 .pin_scl        = 40,
382                 .pin_sda        = 41,
383         },
384 };
385
386 static struct sm501_platdata anubis_sm501_platdata = {
387         .init           = &anubis_sm501_initdata,
388         .gpio_i2c       = anubis_sm501_gpio_i2c,
389         .gpio_i2c_nr    = ARRAY_SIZE(anubis_sm501_gpio_i2c),
390 };
391
392 static struct platform_device anubis_device_sm501 = {
393         .name           = "sm501",
394         .id             = 0,
395         .num_resources  = ARRAY_SIZE(anubis_sm501_resource),
396         .resource       = anubis_sm501_resource,
397         .dev            = {
398                 .platform_data = &anubis_sm501_platdata,
399         },
400 };
401
402 /* Standard Anubis devices */
403
404 static struct platform_device *anubis_devices[] __initdata = {
405         &s3c_device_usb,
406         &s3c_device_wdt,
407         &s3c_device_adc,
408         &s3c_device_i2c,
409         &s3c_device_rtc,
410         &s3c_device_nand,
411         &anubis_device_ide0,
412         &anubis_device_ide1,
413         &anubis_device_asix,
414         &anubis_device_sm501,
415 };
416
417 static struct clk *anubis_clocks[] __initdata = {
418         &s3c24xx_dclk0,
419         &s3c24xx_dclk1,
420         &s3c24xx_clkout0,
421         &s3c24xx_clkout1,
422         &s3c24xx_uclk,
423 };
424
425 /* I2C devices. */
426
427 static struct i2c_board_info anubis_i2c_devs[] __initdata = {
428         {
429                 I2C_BOARD_INFO("tps65011", 0x48),
430                 .irq    = IRQ_EINT20,
431         }
432 };
433
434 static void __init anubis_map_io(void)
435 {
436         /* initialise the clocks */
437
438         s3c24xx_dclk0.parent = &clk_upll;
439         s3c24xx_dclk0.rate   = 12*1000*1000;
440
441         s3c24xx_dclk1.parent = &clk_upll;
442         s3c24xx_dclk1.rate   = 24*1000*1000;
443
444         s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
445         s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
446
447         s3c24xx_uclk.parent  = &s3c24xx_clkout1;
448
449         s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
450
451         s3c_device_nand.dev.platform_data = &anubis_nand_info;
452
453         s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
454         s3c24xx_init_clocks(0);
455         s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
456
457         /* check for the newer revision boards with large page nand */
458
459         if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
460                 printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
461                        __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
462                 anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
463                 anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
464         } else {
465                 /* ensure that the GPIO is setup */
466                 s3c2410_gpio_setpin(S3C2410_GPA0, 1);
467         }
468 }
469
470 static void __init anubis_init(void)
471 {
472         platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
473
474         i2c_register_board_info(0, anubis_i2c_devs,
475                                 ARRAY_SIZE(anubis_i2c_devs));
476 }
477
478
479 MACHINE_START(ANUBIS, "Simtec-Anubis")
480         /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
481         .phys_io        = S3C2410_PA_UART,
482         .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
483         .boot_params    = S3C2410_SDRAM_PA + 0x100,
484         .map_io         = anubis_map_io,
485         .init_machine   = anubis_init,
486         .init_irq       = s3c24xx_init_irq,
487         .timer          = &s3c24xx_timer,
488 MACHINE_END