1/*
2 * linux/arch/arm/mach-pxa/cm-x270.c
3 *
4 * Copyright (C) 2007, 2008 CompuLab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il>
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/platform_device.h>
13#include <linux/irq.h>
14#include <linux/gpio.h>
15#include <linux/delay.h>
16
17#include <linux/rtc-v3020.h>
18#include <video/mbxfb.h>
19
20#include <linux/spi/spi.h>
21#include <linux/spi/pxa2xx_spi.h>
22#include <linux/spi/libertas_spi.h>
23
24#include <mach/pxa27x.h>
25#include <linux/platform_data/usb-ohci-pxa27x.h>
26#include <linux/platform_data/mmc-pxamci.h>
27
28#include "generic.h"
29
30/* physical address if local-bus attached devices */
31#define RTC_PHYS_BASE		(PXA_CS1_PHYS + (5 << 22))
32
33/* GPIO IRQ usage */
34#define GPIO83_MMC_IRQ		(83)
35
36#define CMX270_MMC_IRQ		PXA_GPIO_TO_IRQ(GPIO83_MMC_IRQ)
37
38/* MMC power enable */
39#define GPIO105_MMC_POWER	(105)
40
41/* WLAN GPIOS */
42#define GPIO19_WLAN_STRAP	(19)
43#define GPIO102_WLAN_RST	(102)
44
45static unsigned long cmx270_pin_config[] = {
46	/* AC'97 */
47	GPIO28_AC97_BITCLK,
48	GPIO29_AC97_SDATA_IN_0,
49	GPIO30_AC97_SDATA_OUT,
50	GPIO31_AC97_SYNC,
51	GPIO98_AC97_SYSCLK,
52	GPIO113_AC97_nRESET,
53
54	/* BTUART */
55	GPIO42_BTUART_RXD,
56	GPIO43_BTUART_TXD,
57	GPIO44_BTUART_CTS,
58	GPIO45_BTUART_RTS,
59
60	/* STUART */
61	GPIO46_STUART_RXD,
62	GPIO47_STUART_TXD,
63
64	/* MCI controller */
65	GPIO32_MMC_CLK,
66	GPIO112_MMC_CMD,
67	GPIO92_MMC_DAT_0,
68	GPIO109_MMC_DAT_1,
69	GPIO110_MMC_DAT_2,
70	GPIO111_MMC_DAT_3,
71
72	/* LCD */
73	GPIOxx_LCD_TFT_16BPP,
74
75	/* I2C */
76	GPIO117_I2C_SCL,
77	GPIO118_I2C_SDA,
78
79	/* SSP1 */
80	GPIO23_SSP1_SCLK,
81	GPIO24_SSP1_SFRM,
82	GPIO25_SSP1_TXD,
83	GPIO26_SSP1_RXD,
84
85	/* SSP2 */
86	GPIO19_GPIO,	/* SSP2 clock is used as GPIO for Libertas pin-strap */
87	GPIO14_GPIO,
88	GPIO87_SSP2_TXD,
89	GPIO88_SSP2_RXD,
90
91	/* PC Card */
92	GPIO48_nPOE,
93	GPIO49_nPWE,
94	GPIO50_nPIOR,
95	GPIO51_nPIOW,
96	GPIO85_nPCE_1,
97	GPIO54_nPCE_2,
98	GPIO55_nPREG,
99	GPIO56_nPWAIT,
100	GPIO57_nIOIS16,
101
102	/* SDRAM and local bus */
103	GPIO15_nCS_1,
104	GPIO78_nCS_2,
105	GPIO79_nCS_3,
106	GPIO80_nCS_4,
107	GPIO33_nCS_5,
108	GPIO49_nPWE,
109	GPIO18_RDY,
110
111	/* GPIO */
112	GPIO0_GPIO	| WAKEUP_ON_EDGE_BOTH,
113	GPIO105_GPIO	| MFP_LPM_DRIVE_HIGH,	/* MMC/SD power */
114	GPIO53_GPIO,				/* PC card reset */
115	GPIO102_GPIO,				/* WLAN reset */
116
117	/* NAND controls */
118	GPIO11_GPIO	| MFP_LPM_DRIVE_HIGH,	/* NAND CE# */
119	GPIO89_GPIO,				/* NAND Ready/Busy */
120
121	/* interrupts */
122	GPIO10_GPIO,	/* DM9000 interrupt */
123	GPIO83_GPIO,	/* MMC card detect */
124	GPIO95_GPIO,	/* WLAN interrupt */
125};
126
127/* V3020 RTC */
128#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
129static struct resource cmx270_v3020_resource[] = {
130	[0] = {
131		.start = RTC_PHYS_BASE,
132		.end   = RTC_PHYS_BASE + 4,
133		.flags = IORESOURCE_MEM,
134	},
135};
136
137struct v3020_platform_data cmx270_v3020_pdata = {
138	.leftshift = 16,
139};
140
141static struct platform_device cmx270_rtc_device = {
142	.name		= "v3020",
143	.num_resources	= ARRAY_SIZE(cmx270_v3020_resource),
144	.resource	= cmx270_v3020_resource,
145	.id		= -1,
146	.dev		= {
147		.platform_data = &cmx270_v3020_pdata,
148	}
149};
150
151static void __init cmx270_init_rtc(void)
152{
153	platform_device_register(&cmx270_rtc_device);
154}
155#else
156static inline void cmx270_init_rtc(void) {}
157#endif
158
159/* 2700G graphics */
160#if defined(CONFIG_FB_MBX) || defined(CONFIG_FB_MBX_MODULE)
161static u64 fb_dma_mask = ~(u64)0;
162
163static struct resource cmx270_2700G_resource[] = {
164	/* frame buffer memory including ODFB and External SDRAM */
165	[0] = {
166		.start = PXA_CS2_PHYS,
167		.end   = PXA_CS2_PHYS + 0x01ffffff,
168		.flags = IORESOURCE_MEM,
169	},
170	/* Marathon registers */
171	[1] = {
172		.start = PXA_CS2_PHYS + 0x03fe0000,
173		.end   = PXA_CS2_PHYS + 0x03ffffff,
174		.flags = IORESOURCE_MEM,
175	},
176};
177
178static unsigned long cmx270_marathon_on[] = {
179	GPIO58_GPIO,
180	GPIO59_GPIO,
181	GPIO60_GPIO,
182	GPIO61_GPIO,
183	GPIO62_GPIO,
184	GPIO63_GPIO,
185	GPIO64_GPIO,
186	GPIO65_GPIO,
187	GPIO66_GPIO,
188	GPIO67_GPIO,
189	GPIO68_GPIO,
190	GPIO69_GPIO,
191	GPIO70_GPIO,
192	GPIO71_GPIO,
193	GPIO72_GPIO,
194	GPIO73_GPIO,
195	GPIO74_GPIO,
196	GPIO75_GPIO,
197	GPIO76_GPIO,
198	GPIO77_GPIO,
199};
200
201static unsigned long cmx270_marathon_off[] = {
202	GPIOxx_LCD_TFT_16BPP,
203};
204
205static int cmx270_marathon_probe(struct fb_info *fb)
206{
207	int gpio, err;
208
209	for (gpio = 58; gpio <= 77; gpio++) {
210		err = gpio_request(gpio, "LCD");
211		if (err)
212			return err;
213		gpio_direction_input(gpio);
214	}
215
216	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_marathon_on));
217	return 0;
218}
219
220static int cmx270_marathon_remove(struct fb_info *fb)
221{
222	int gpio;
223
224	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_marathon_off));
225
226	for (gpio = 58; gpio <= 77; gpio++)
227		gpio_free(gpio);
228
229	return 0;
230}
231
232static struct mbxfb_platform_data cmx270_2700G_data = {
233	.xres = {
234		.min = 240,
235		.max = 1200,
236		.defval = 640,
237	},
238	.yres = {
239		.min = 240,
240		.max = 1200,
241		.defval = 480,
242	},
243	.bpp = {
244		.min = 16,
245		.max = 32,
246		.defval = 16,
247	},
248	.memsize = 8*1024*1024,
249	.probe = cmx270_marathon_probe,
250	.remove = cmx270_marathon_remove,
251};
252
253static struct platform_device cmx270_2700G = {
254	.name		= "mbx-fb",
255	.dev		= {
256		.platform_data	= &cmx270_2700G_data,
257		.dma_mask	= &fb_dma_mask,
258		.coherent_dma_mask = 0xffffffff,
259	},
260	.num_resources	= ARRAY_SIZE(cmx270_2700G_resource),
261	.resource	= cmx270_2700G_resource,
262	.id		= -1,
263};
264
265static void __init cmx270_init_2700G(void)
266{
267	platform_device_register(&cmx270_2700G);
268}
269#else
270static inline void cmx270_init_2700G(void) {}
271#endif
272
273/* PXA27x OHCI controller setup */
274#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
275static struct pxaohci_platform_data cmx270_ohci_platform_data = {
276	.port_mode	= PMM_PERPORT_MODE,
277	.flags		= ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
278};
279
280static void __init cmx270_init_ohci(void)
281{
282	pxa_set_ohci_info(&cmx270_ohci_platform_data);
283}
284#else
285static inline void cmx270_init_ohci(void) {}
286#endif
287
288#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
289static struct pxamci_platform_data cmx270_mci_platform_data = {
290	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
291	.gpio_card_detect	= GPIO83_MMC_IRQ,
292	.gpio_card_ro		= -1,
293	.gpio_power		= GPIO105_MMC_POWER,
294	.gpio_power_invert	= 1,
295};
296
297static void __init cmx270_init_mmc(void)
298{
299	pxa_set_mci_info(&cmx270_mci_platform_data);
300}
301#else
302static inline void cmx270_init_mmc(void) {}
303#endif
304
305#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
306static struct pxa2xx_spi_master cm_x270_spi_info = {
307	.num_chipselect	= 1,
308	.enable_dma	= 1,
309};
310
311static struct pxa2xx_spi_chip cm_x270_libertas_chip = {
312	.rx_threshold	= 1,
313	.tx_threshold	= 1,
314	.timeout	= 1000,
315	.gpio_cs	= 14,
316};
317
318static unsigned long cm_x270_libertas_pin_config[] = {
319	/* SSP2 */
320	GPIO19_SSP2_SCLK,
321	GPIO14_GPIO,
322	GPIO87_SSP2_TXD,
323	GPIO88_SSP2_RXD,
324
325};
326
327static int cm_x270_libertas_setup(struct spi_device *spi)
328{
329	int err = gpio_request(GPIO19_WLAN_STRAP, "WLAN STRAP");
330	if (err)
331		return err;
332
333	err = gpio_request(GPIO102_WLAN_RST, "WLAN RST");
334	if (err)
335		goto err_free_strap;
336
337	err = gpio_direction_output(GPIO102_WLAN_RST, 0);
338	if (err)
339		goto err_free_strap;
340	msleep(100);
341
342	err = gpio_direction_output(GPIO19_WLAN_STRAP, 1);
343	if (err)
344		goto err_free_strap;
345	msleep(100);
346
347	pxa2xx_mfp_config(ARRAY_AND_SIZE(cm_x270_libertas_pin_config));
348
349	gpio_set_value(GPIO102_WLAN_RST, 1);
350	msleep(100);
351
352	spi->bits_per_word = 16;
353	spi_setup(spi);
354
355	return 0;
356
357err_free_strap:
358	gpio_free(GPIO19_WLAN_STRAP);
359
360	return err;
361}
362
363static int cm_x270_libertas_teardown(struct spi_device *spi)
364{
365	gpio_set_value(GPIO102_WLAN_RST, 0);
366	gpio_free(GPIO102_WLAN_RST);
367	gpio_free(GPIO19_WLAN_STRAP);
368
369	return 0;
370}
371
372struct libertas_spi_platform_data cm_x270_libertas_pdata = {
373	.use_dummy_writes	= 1,
374	.setup			= cm_x270_libertas_setup,
375	.teardown		= cm_x270_libertas_teardown,
376};
377
378static struct spi_board_info cm_x270_spi_devices[] __initdata = {
379	{
380		.modalias		= "libertas_spi",
381		.max_speed_hz		= 13000000,
382		.bus_num		= 2,
383		.irq			= PXA_GPIO_TO_IRQ(95),
384		.chip_select		= 0,
385		.controller_data	= &cm_x270_libertas_chip,
386		.platform_data		= &cm_x270_libertas_pdata,
387	},
388};
389
390static void __init cmx270_init_spi(void)
391{
392	pxa2xx_set_spi_info(2, &cm_x270_spi_info);
393	spi_register_board_info(ARRAY_AND_SIZE(cm_x270_spi_devices));
394}
395#else
396static inline void cmx270_init_spi(void) {}
397#endif
398
399void __init cmx270_init(void)
400{
401	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
402
403#ifdef CONFIG_PM
404	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
405#endif
406
407	cmx270_init_rtc();
408	cmx270_init_mmc();
409	cmx270_init_ohci();
410	cmx270_init_2700G();
411	cmx270_init_spi();
412}
413