1/*
2 *  linux/arch/arm/mach-pxa/colibri-pxa270.c
3 *
4 *  Support for Toradex PXA270 based Colibri module
5 *  Daniel Mack <daniel@caiaq.de>
6 *  Marek Vasut <marek.vasut@gmail.com>
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License version 2 as
10 *  published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/moduleparam.h>
16#include <linux/kernel.h>
17#include <linux/mtd/mtd.h>
18#include <linux/mtd/partitions.h>
19#include <linux/mtd/physmap.h>
20#include <linux/platform_device.h>
21#include <linux/ucb1400.h>
22
23#include <asm/mach/arch.h>
24#include <asm/mach/flash.h>
25#include <asm/mach-types.h>
26#include <asm/sizes.h>
27
28#include <mach/audio.h>
29#include <mach/colibri.h>
30#include <mach/pxa27x.h>
31
32#include "devices.h"
33#include "generic.h"
34
35/******************************************************************************
36 * Evaluation board MFP
37 ******************************************************************************/
38#ifdef	 CONFIG_MACH_COLIBRI_EVALBOARD
39static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {
40	/* MMC */
41	GPIO32_MMC_CLK,
42	GPIO92_MMC_DAT_0,
43	GPIO109_MMC_DAT_1,
44	GPIO110_MMC_DAT_2,
45	GPIO111_MMC_DAT_3,
46	GPIO112_MMC_CMD,
47	GPIO0_GPIO,	/* SD detect */
48
49	/* FFUART */
50	GPIO39_FFUART_TXD,
51	GPIO34_FFUART_RXD,
52
53	/* UHC */
54	GPIO88_USBH1_PWR,
55	GPIO89_USBH1_PEN,
56	GPIO119_USBH2_PWR,
57	GPIO120_USBH2_PEN,
58
59	/* PCMCIA */
60	GPIO85_nPCE_1,
61	GPIO54_nPCE_2,
62	GPIO55_nPREG,
63	GPIO50_nPIOR,
64	GPIO51_nPIOW,
65	GPIO49_nPWE,
66	GPIO48_nPOE,
67	GPIO57_nIOIS16,
68	GPIO56_nPWAIT,
69	GPIO104_PSKTSEL,
70	GPIO53_GPIO,	/* RESET */
71	GPIO83_GPIO,	/* BVD1 */
72	GPIO82_GPIO,	/* BVD2 */
73	GPIO1_GPIO,	/* READY */
74	GPIO84_GPIO,	/* DETECT */
75	GPIO107_GPIO,	/* PPEN */
76
77	/* I2C */
78	GPIO117_I2C_SCL,
79	GPIO118_I2C_SDA,
80};
81#else
82static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {};
83#endif
84
85#ifdef	CONFIG_MACH_COLIBRI_PXA270_INCOME
86static mfp_cfg_t income_pin_config[] __initdata = {
87	/* MMC */
88	GPIO32_MMC_CLK,
89	GPIO92_MMC_DAT_0,
90	GPIO109_MMC_DAT_1,
91	GPIO110_MMC_DAT_2,
92	GPIO111_MMC_DAT_3,
93	GPIO112_MMC_CMD,
94	GPIO0_GPIO,	/* SD detect */
95	GPIO1_GPIO,	/* SD read-only */
96
97	/* FFUART */
98	GPIO39_FFUART_TXD,
99	GPIO34_FFUART_RXD,
100
101	/* BFUART */
102	GPIO42_BTUART_RXD,
103	GPIO43_BTUART_TXD,
104	GPIO45_BTUART_RTS,
105
106	/* STUART */
107	GPIO46_STUART_RXD,
108	GPIO47_STUART_TXD,
109
110	/* UHC */
111	GPIO88_USBH1_PWR,
112	GPIO89_USBH1_PEN,
113
114	/* LCD */
115	GPIOxx_LCD_TFT_16BPP,
116
117	/* PWM */
118	GPIO16_PWM0_OUT,
119
120	/* I2C */
121	GPIO117_I2C_SCL,
122	GPIO118_I2C_SDA,
123
124	/* LED */
125	GPIO54_GPIO,	/* LED A */
126	GPIO55_GPIO,	/* LED B */
127};
128#else
129static mfp_cfg_t income_pin_config[] __initdata = {};
130#endif
131
132/******************************************************************************
133 * Pin configuration
134 ******************************************************************************/
135static mfp_cfg_t colibri_pxa270_pin_config[] __initdata = {
136	/* Ethernet */
137	GPIO78_nCS_2,	/* Ethernet CS */
138	GPIO114_GPIO,	/* Ethernet IRQ */
139
140	/* AC97 */
141	GPIO28_AC97_BITCLK,
142	GPIO29_AC97_SDATA_IN_0,
143	GPIO30_AC97_SDATA_OUT,
144	GPIO31_AC97_SYNC,
145	GPIO95_AC97_nRESET,
146	GPIO98_AC97_SYSCLK,
147	GPIO113_GPIO,	/* Touchscreen IRQ */
148};
149
150/******************************************************************************
151 * NOR Flash
152 ******************************************************************************/
153#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
154static struct mtd_partition colibri_partitions[] = {
155	{
156		.name =		"Bootloader",
157		.offset =	0x00000000,
158		.size =		0x00040000,
159		.mask_flags =	MTD_WRITEABLE	/* force read-only */
160	}, {
161		.name =		"Kernel",
162		.offset =	0x00040000,
163		.size =		0x00400000,
164		.mask_flags =	0
165	}, {
166		.name =		"Rootfs",
167		.offset =	0x00440000,
168		.size =		MTDPART_SIZ_FULL,
169		.mask_flags =	0
170	}
171};
172
173static struct physmap_flash_data colibri_flash_data[] = {
174	{
175		.width		= 4,			/* bankwidth in bytes */
176		.parts		= colibri_partitions,
177		.nr_parts	= ARRAY_SIZE(colibri_partitions)
178	}
179};
180
181static struct resource colibri_pxa270_flash_resource = {
182	.start	= PXA_CS0_PHYS,
183	.end	= PXA_CS0_PHYS + SZ_32M - 1,
184	.flags	= IORESOURCE_MEM,
185};
186
187static struct platform_device colibri_pxa270_flash_device = {
188	.name	= "physmap-flash",
189	.id	= 0,
190	.dev 	= {
191		.platform_data = colibri_flash_data,
192	},
193	.resource = &colibri_pxa270_flash_resource,
194	.num_resources = 1,
195};
196
197static void __init colibri_pxa270_nor_init(void)
198{
199	platform_device_register(&colibri_pxa270_flash_device);
200}
201#else
202static inline void colibri_pxa270_nor_init(void) {}
203#endif
204
205/******************************************************************************
206 * Ethernet
207 ******************************************************************************/
208#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
209static struct resource colibri_pxa270_dm9000_resources[] = {
210	{
211		.start	= PXA_CS2_PHYS,
212		.end	= PXA_CS2_PHYS + 3,
213		.flags	= IORESOURCE_MEM,
214	},
215	{
216		.start	= PXA_CS2_PHYS + 4,
217		.end	= PXA_CS2_PHYS + 4 + 500,
218		.flags	= IORESOURCE_MEM,
219	},
220	{
221		.start	= PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ),
222		.end	= PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ),
223		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
224	},
225};
226
227static struct platform_device colibri_pxa270_dm9000_device = {
228	.name		= "dm9000",
229	.id		= -1,
230	.num_resources	= ARRAY_SIZE(colibri_pxa270_dm9000_resources),
231	.resource	= colibri_pxa270_dm9000_resources,
232};
233
234static void __init colibri_pxa270_eth_init(void)
235{
236	platform_device_register(&colibri_pxa270_dm9000_device);
237}
238#else
239static inline void colibri_pxa270_eth_init(void) {}
240#endif
241
242/******************************************************************************
243 * Audio and Touchscreen
244 ******************************************************************************/
245#if	defined(CONFIG_TOUCHSCREEN_UCB1400) || \
246	defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
247static pxa2xx_audio_ops_t colibri_pxa270_ac97_pdata = {
248	.reset_gpio	= 95,
249};
250
251static struct ucb1400_pdata colibri_pxa270_ucb1400_pdata = {
252	.irq		= PXA_GPIO_TO_IRQ(GPIO113_COLIBRI_PXA270_TS_IRQ),
253};
254
255static struct platform_device colibri_pxa270_ucb1400_device = {
256	.name		= "ucb1400_core",
257	.id		= -1,
258	.dev		= {
259		.platform_data = &colibri_pxa270_ucb1400_pdata,
260	},
261};
262
263static void __init colibri_pxa270_tsc_init(void)
264{
265	pxa_set_ac97_info(&colibri_pxa270_ac97_pdata);
266	platform_device_register(&colibri_pxa270_ucb1400_device);
267}
268#else
269static inline void colibri_pxa270_tsc_init(void) {}
270#endif
271
272static int colibri_pxa270_baseboard;
273core_param(colibri_pxa270_baseboard, colibri_pxa270_baseboard, int, 0444);
274
275static void __init colibri_pxa270_init(void)
276{
277	pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa270_pin_config));
278
279	colibri_pxa270_nor_init();
280	colibri_pxa270_eth_init();
281	colibri_pxa270_tsc_init();
282
283	switch (colibri_pxa270_baseboard) {
284	case COLIBRI_EVALBOARD:
285		pxa2xx_mfp_config(ARRAY_AND_SIZE(
286			colibri_pxa270_evalboard_pin_config));
287		colibri_evalboard_init();
288		break;
289	case COLIBRI_PXA270_INCOME:
290		pxa2xx_mfp_config(ARRAY_AND_SIZE(income_pin_config));
291		colibri_pxa270_income_boardinit();
292		break;
293	default:
294		printk(KERN_ERR "Illegal colibri_pxa270_baseboard type %d\n",
295				colibri_pxa270_baseboard);
296	}
297}
298
299/* The "Income s.r.o. SH-Dmaster PXA270 SBC" board can be booted either
300 * with the INCOME mach type or with COLIBRI and the kernel parameter
301 * "colibri_pxa270_baseboard=1"
302 */
303static void __init colibri_pxa270_income_init(void)
304{
305	colibri_pxa270_baseboard = COLIBRI_PXA270_INCOME;
306	colibri_pxa270_init();
307}
308
309MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
310	.atag_offset	= 0x100,
311	.init_machine	= colibri_pxa270_init,
312	.map_io		= pxa27x_map_io,
313	.nr_irqs	= PXA_NR_IRQS,
314	.init_irq	= pxa27x_init_irq,
315	.handle_irq	= pxa27x_handle_irq,
316	.init_time	= pxa_timer_init,
317	.restart	= pxa_restart,
318MACHINE_END
319
320MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
321	.atag_offset	= 0x100,
322	.init_machine	= colibri_pxa270_income_init,
323	.map_io		= pxa27x_map_io,
324	.nr_irqs	= PXA_NR_IRQS,
325	.init_irq	= pxa27x_init_irq,
326	.handle_irq	= pxa27x_handle_irq,
327	.init_time	= pxa_timer_init,
328	.restart	= pxa_restart,
329MACHINE_END
330
331