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