1/* linux/arch/arm/mach-s3c2440/mach-anubis.c
2 *
3 * Copyright (c) 2003-2005 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
21#include <asm/mach/arch.h>
22#include <asm/mach/map.h>
23#include <asm/mach/irq.h>
24
25#include <asm/arch/anubis-map.h>
26#include <asm/arch/anubis-irq.h>
27#include <asm/arch/anubis-cpld.h>
28
29#include <asm/hardware.h>
30#include <asm/io.h>
31#include <asm/irq.h>
32#include <asm/mach-types.h>
33
34#include <asm/arch/regs-serial.h>
35#include <asm/arch/regs-gpio.h>
36#include <asm/arch/regs-mem.h>
37#include <asm/arch/regs-lcd.h>
38#include <asm/arch/nand.h>
39
40#include <linux/mtd/mtd.h>
41#include <linux/mtd/nand.h>
42#include <linux/mtd/nand_ecc.h>
43#include <linux/mtd/partitions.h>
44
45#include <asm/plat-s3c24xx/clock.h>
46#include <asm/plat-s3c24xx/devs.h>
47#include <asm/plat-s3c24xx/cpu.h>
48
49#define COPYRIGHT ", (c) 2005 Simtec Electronics"
50
51static struct map_desc anubis_iodesc[] __initdata = {
52  /* ISA IO areas */
53
54  {
55	.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
56	.pfn		= __phys_to_pfn(0x0),
57	.length		= SZ_4M,
58	.type		= MT_DEVICE,
59  }, {
60	.virtual	= (u32)S3C24XX_VA_ISA_WORD,
61	.pfn		= __phys_to_pfn(0x0),
62	.length 	= SZ_4M,
63	.type		= MT_DEVICE,
64  },
65
66  /* we could possibly compress the next set down into a set of smaller tables
67   * pagetables, but that would mean using an L2 section, and it still means
68   * we cannot actually feed the same register to an LDR due to 16K spacing
69   */
70
71  /* CPLD control registers */
72
73  {
74	.virtual	= (u32)ANUBIS_VA_CTRL1,
75	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL1),
76	.length		= SZ_4K,
77	.type		= MT_DEVICE,
78  }, {
79	.virtual	= (u32)ANUBIS_VA_IDREG,
80	.pfn		= __phys_to_pfn(ANUBIS_PA_IDREG),
81	.length		= SZ_4K,
82	.type		= MT_DEVICE,
83  },
84};
85
86#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
87#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
88#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
89
90static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
91	[0] = {
92		.name		= "uclk",
93		.divisor	= 1,
94		.min_baud	= 0,
95		.max_baud	= 0,
96	},
97	[1] = {
98		.name		= "pclk",
99		.divisor	= 1,
100		.min_baud	= 0,
101		.max_baud	= 0,
102	}
103};
104
105
106static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
107	[0] = {
108		.hwport	     = 0,
109		.flags	     = 0,
110		.ucon	     = UCON,
111		.ulcon	     = ULCON,
112		.ufcon	     = UFCON,
113		.clocks	     = anubis_serial_clocks,
114		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
115	},
116	[1] = {
117		.hwport	     = 2,
118		.flags	     = 0,
119		.ucon	     = UCON,
120		.ulcon	     = ULCON,
121		.ufcon	     = UFCON,
122		.clocks	     = anubis_serial_clocks,
123		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
124	},
125};
126
127/* NAND Flash on Anubis board */
128
129static int external_map[]   = { 2 };
130static int chip0_map[]      = { 0 };
131static int chip1_map[]      = { 1 };
132
133static struct mtd_partition anubis_default_nand_part[] = {
134	[0] = {
135		.name	= "Boot Agent",
136		.size	= SZ_16K,
137		.offset	= 0,
138	},
139	[1] = {
140		.name	= "/boot",
141		.size	= SZ_4M - SZ_16K,
142		.offset	= SZ_16K,
143	},
144	[2] = {
145		.name	= "user1",
146		.offset	= SZ_4M,
147		.size	= SZ_32M - SZ_4M,
148	},
149	[3] = {
150		.name	= "user2",
151		.offset	= SZ_32M,
152		.size	= MTDPART_SIZ_FULL,
153	}
154};
155
156/* the Anubis has 3 selectable slots for nand-flash, the two
157 * on-board chip areas, as well as the external slot.
158 *
159 * Note, there is no current hot-plug support for the External
160 * socket.
161*/
162
163static struct s3c2410_nand_set anubis_nand_sets[] = {
164	[1] = {
165		.name		= "External",
166		.nr_chips	= 1,
167		.nr_map		= external_map,
168		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
169		.partitions	= anubis_default_nand_part,
170	},
171	[0] = {
172		.name		= "chip0",
173		.nr_chips	= 1,
174		.nr_map		= chip0_map,
175		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
176		.partitions	= anubis_default_nand_part,
177	},
178	[2] = {
179		.name		= "chip1",
180		.nr_chips	= 1,
181		.nr_map		= chip1_map,
182		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
183		.partitions	= anubis_default_nand_part,
184	},
185};
186
187static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
188{
189	unsigned int tmp;
190
191	slot = set->nr_map[slot] & 3;
192
193	pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
194		 slot, set, set->nr_map);
195
196	tmp = __raw_readb(ANUBIS_VA_CTRL1);
197	tmp &= ~ANUBIS_CTRL1_NANDSEL;
198	tmp |= slot;
199
200	pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
201
202	__raw_writeb(tmp, ANUBIS_VA_CTRL1);
203}
204
205static struct s3c2410_platform_nand anubis_nand_info = {
206	.tacls		= 25,
207	.twrph0		= 55,
208	.twrph1		= 40,
209	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
210	.sets		= anubis_nand_sets,
211	.select_chip	= anubis_nand_select,
212};
213
214/* IDE channels */
215
216static struct resource anubis_ide0_resource[] = {
217	{
218		.start	= S3C2410_CS3,
219		.end	= S3C2410_CS3 + (8*32) - 1,
220		.flags	= IORESOURCE_MEM,
221	}, {
222		.start	= S3C2410_CS3 + (1<<26),
223		.end	= S3C2410_CS3 + (1<<26) + (8*32) - 1,
224		.flags	= IORESOURCE_MEM,
225	}, {
226		.start	= IRQ_IDE0,
227		.end	= IRQ_IDE0,
228		.flags	= IORESOURCE_IRQ,
229	},
230};
231
232static struct platform_device anubis_device_ide0 = {
233	.name		= "simtec-ide",
234	.id		= 0,
235	.num_resources	= ARRAY_SIZE(anubis_ide0_resource),
236	.resource	= anubis_ide0_resource,
237};
238
239static struct resource anubis_ide1_resource[] = {
240	{
241		.start	= S3C2410_CS4,
242		.end	= S3C2410_CS4 + (8*32) - 1,
243		.flags	= IORESOURCE_MEM,
244	}, {
245		.start	= S3C2410_CS4 + (1<<26),
246		.end	= S3C2410_CS4 + (1<<26) + (8*32) - 1,
247		.flags	= IORESOURCE_MEM,
248	}, {
249		.start	= IRQ_IDE0,
250		.end	= IRQ_IDE0,
251		.flags	= IORESOURCE_IRQ,
252	},
253};
254
255
256static struct platform_device anubis_device_ide1 = {
257	.name		= "simtec-ide",
258	.id		= 1,
259	.num_resources	= ARRAY_SIZE(anubis_ide1_resource),
260	.resource	= anubis_ide1_resource,
261};
262
263/* Standard Anubis devices */
264
265static struct platform_device *anubis_devices[] __initdata = {
266	&s3c_device_usb,
267	&s3c_device_wdt,
268	&s3c_device_adc,
269	&s3c_device_i2c,
270 	&s3c_device_rtc,
271	&s3c_device_nand,
272	&anubis_device_ide0,
273	&anubis_device_ide1,
274};
275
276static struct clk *anubis_clocks[] = {
277	&s3c24xx_dclk0,
278	&s3c24xx_dclk1,
279	&s3c24xx_clkout0,
280	&s3c24xx_clkout1,
281	&s3c24xx_uclk,
282};
283
284static void __init anubis_map_io(void)
285{
286	/* initialise the clocks */
287
288	s3c24xx_dclk0.parent = NULL;
289	s3c24xx_dclk0.rate   = 12*1000*1000;
290
291	s3c24xx_dclk1.parent = NULL;
292	s3c24xx_dclk1.rate   = 24*1000*1000;
293
294	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
295	s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
296
297	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
298
299	s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
300
301	s3c_device_nand.dev.platform_data = &anubis_nand_info;
302
303	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
304	s3c24xx_init_clocks(0);
305	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
306
307	/* ensure that the GPIO is setup */
308	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
309}
310
311static void __init anubis_init(void)
312{
313	platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
314}
315
316
317MACHINE_START(ANUBIS, "Simtec-Anubis")
318	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
319	.phys_io	= S3C2410_PA_UART,
320	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
321	.boot_params	= S3C2410_SDRAM_PA + 0x100,
322	.map_io		= anubis_map_io,
323	.init_machine	= anubis_init,
324	.init_irq	= s3c24xx_init_irq,
325	.timer		= &s3c24xx_timer,
326MACHINE_END
327