1f59c811fSManuel Lauss /*
2f59c811fSManuel Lauss  * DBAu1000/1500/1100 board support
3f59c811fSManuel Lauss  *
4f59c811fSManuel Lauss  * Copyright 2000, 2008 MontaVista Software Inc.
5f59c811fSManuel Lauss  * Author: MontaVista Software, Inc. <source@mvista.com>
6f59c811fSManuel Lauss  *
7f59c811fSManuel Lauss  * This program is free software; you can redistribute it and/or modify
8f59c811fSManuel Lauss  * it under the terms of the GNU General Public License as published by
9f59c811fSManuel Lauss  * the Free Software Foundation; either version 2 of the License, or
10f59c811fSManuel Lauss  * (at your option) any later version.
11f59c811fSManuel Lauss  *
12f59c811fSManuel Lauss  * This program is distributed in the hope that it will be useful,
13f59c811fSManuel Lauss  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f59c811fSManuel Lauss  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15f59c811fSManuel Lauss  * GNU General Public License for more details.
16f59c811fSManuel Lauss  *
17f59c811fSManuel Lauss  * You should have received a copy of the GNU General Public License
18f59c811fSManuel Lauss  * along with this program; if not, write to the Free Software
19f59c811fSManuel Lauss  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20f59c811fSManuel Lauss  */
21f59c811fSManuel Lauss 
22f59c811fSManuel Lauss #include <linux/dma-mapping.h>
23f59c811fSManuel Lauss #include <linux/gpio.h>
24f59c811fSManuel Lauss #include <linux/init.h>
25f59c811fSManuel Lauss #include <linux/interrupt.h>
26c9af5144SManuel Lauss #include <linux/leds.h>
27c9af5144SManuel Lauss #include <linux/mmc/host.h>
28c9af5144SManuel Lauss #include <linux/module.h>
29f59c811fSManuel Lauss #include <linux/platform_device.h>
30f59c811fSManuel Lauss #include <linux/pm.h>
312a32daf1SManuel Lauss #include <linux/spi/spi.h>
322a32daf1SManuel Lauss #include <linux/spi/spi_gpio.h>
332a32daf1SManuel Lauss #include <linux/spi/ads7846.h>
34f59c811fSManuel Lauss #include <asm/mach-au1x00/au1000.h>
35f59c811fSManuel Lauss #include <asm/mach-au1x00/au1000_dma.h>
36c9af5144SManuel Lauss #include <asm/mach-au1x00/au1100_mmc.h>
37f59c811fSManuel Lauss #include <asm/mach-db1x00/bcsr.h>
38f59c811fSManuel Lauss #include <asm/reboot.h>
39f59c811fSManuel Lauss #include <prom.h>
40f59c811fSManuel Lauss #include "platform.h"
41f59c811fSManuel Lauss 
42f59c811fSManuel Lauss #define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT)
43f59c811fSManuel Lauss 
44f59c811fSManuel Lauss struct pci_dev;
45f59c811fSManuel Lauss 
46f59c811fSManuel Lauss static const char *board_type_str(void)
47f59c811fSManuel Lauss {
48f59c811fSManuel Lauss 	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
49f59c811fSManuel Lauss 	case BCSR_WHOAMI_DB1000:
50f59c811fSManuel Lauss 		return "DB1000";
51f59c811fSManuel Lauss 	case BCSR_WHOAMI_DB1500:
52f59c811fSManuel Lauss 		return "DB1500";
53f59c811fSManuel Lauss 	case BCSR_WHOAMI_DB1100:
54f59c811fSManuel Lauss 		return "DB1100";
55f59c811fSManuel Lauss 	default:
56f59c811fSManuel Lauss 		return "(unknown)";
57f59c811fSManuel Lauss 	}
58f59c811fSManuel Lauss }
59f59c811fSManuel Lauss 
60f59c811fSManuel Lauss const char *get_system_type(void)
61f59c811fSManuel Lauss {
62f59c811fSManuel Lauss 	return board_type_str();
63f59c811fSManuel Lauss }
64f59c811fSManuel Lauss 
65f59c811fSManuel Lauss void __init board_setup(void)
66f59c811fSManuel Lauss {
67f59c811fSManuel Lauss 	/* initialize board register space */
68f59c811fSManuel Lauss 	bcsr_init(DB1000_BCSR_PHYS_ADDR,
69f59c811fSManuel Lauss 		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
70f59c811fSManuel Lauss 
71f59c811fSManuel Lauss 	printk(KERN_INFO "AMD Alchemy %s Board\n", board_type_str());
72f59c811fSManuel Lauss }
73f59c811fSManuel Lauss 
74f59c811fSManuel Lauss 
75f59c811fSManuel Lauss static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
76f59c811fSManuel Lauss {
77f59c811fSManuel Lauss 	if ((slot < 12) || (slot > 13) || pin == 0)
78f59c811fSManuel Lauss 		return -1;
79f59c811fSManuel Lauss 	if (slot == 12)
80f59c811fSManuel Lauss 		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
81f59c811fSManuel Lauss 	if (slot == 13) {
82f59c811fSManuel Lauss 		switch (pin) {
83f59c811fSManuel Lauss 		case 1: return AU1500_PCI_INTA;
84f59c811fSManuel Lauss 		case 2: return AU1500_PCI_INTB;
85f59c811fSManuel Lauss 		case 3: return AU1500_PCI_INTC;
86f59c811fSManuel Lauss 		case 4: return AU1500_PCI_INTD;
87f59c811fSManuel Lauss 		}
88f59c811fSManuel Lauss 	}
89f59c811fSManuel Lauss 	return -1;
90f59c811fSManuel Lauss }
91f59c811fSManuel Lauss 
92f59c811fSManuel Lauss static struct resource alchemy_pci_host_res[] = {
93f59c811fSManuel Lauss 	[0] = {
94f59c811fSManuel Lauss 		.start	= AU1500_PCI_PHYS_ADDR,
95f59c811fSManuel Lauss 		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
96f59c811fSManuel Lauss 		.flags	= IORESOURCE_MEM,
97f59c811fSManuel Lauss 	},
98f59c811fSManuel Lauss };
99f59c811fSManuel Lauss 
100f59c811fSManuel Lauss static struct alchemy_pci_platdata db1500_pci_pd = {
101f59c811fSManuel Lauss 	.board_map_irq	= db1500_map_pci_irq,
102f59c811fSManuel Lauss };
103f59c811fSManuel Lauss 
104f59c811fSManuel Lauss static struct platform_device db1500_pci_host_dev = {
105f59c811fSManuel Lauss 	.dev.platform_data = &db1500_pci_pd,
106f59c811fSManuel Lauss 	.name		= "alchemy-pci",
107f59c811fSManuel Lauss 	.id		= 0,
108f59c811fSManuel Lauss 	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
109f59c811fSManuel Lauss 	.resource	= alchemy_pci_host_res,
110f59c811fSManuel Lauss };
111f59c811fSManuel Lauss 
112f59c811fSManuel Lauss static int __init db1500_pci_init(void)
113f59c811fSManuel Lauss {
114f59c811fSManuel Lauss 	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1500)
115f59c811fSManuel Lauss 		return platform_device_register(&db1500_pci_host_dev);
116f59c811fSManuel Lauss 	return 0;
117f59c811fSManuel Lauss }
118f59c811fSManuel Lauss /* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
119f59c811fSManuel Lauss arch_initcall(db1500_pci_init);
120f59c811fSManuel Lauss 
121f59c811fSManuel Lauss 
122f59c811fSManuel Lauss static struct resource au1100_lcd_resources[] = {
123f59c811fSManuel Lauss 	[0] = {
124f59c811fSManuel Lauss 		.start	= AU1100_LCD_PHYS_ADDR,
125f59c811fSManuel Lauss 		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
126f59c811fSManuel Lauss 		.flags	= IORESOURCE_MEM,
127f59c811fSManuel Lauss 	},
128f59c811fSManuel Lauss 	[1] = {
129f59c811fSManuel Lauss 		.start	= AU1100_LCD_INT,
130f59c811fSManuel Lauss 		.end	= AU1100_LCD_INT,
131f59c811fSManuel Lauss 		.flags	= IORESOURCE_IRQ,
132f59c811fSManuel Lauss 	}
133f59c811fSManuel Lauss };
134f59c811fSManuel Lauss 
135f59c811fSManuel Lauss static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
136f59c811fSManuel Lauss 
137f59c811fSManuel Lauss static struct platform_device au1100_lcd_device = {
138f59c811fSManuel Lauss 	.name		= "au1100-lcd",
139f59c811fSManuel Lauss 	.id		= 0,
140f59c811fSManuel Lauss 	.dev = {
141f59c811fSManuel Lauss 		.dma_mask		= &au1100_lcd_dmamask,
142f59c811fSManuel Lauss 		.coherent_dma_mask	= DMA_BIT_MASK(32),
143f59c811fSManuel Lauss 	},
144f59c811fSManuel Lauss 	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
145f59c811fSManuel Lauss 	.resource	= au1100_lcd_resources,
146f59c811fSManuel Lauss };
147f59c811fSManuel Lauss 
148f59c811fSManuel Lauss static struct resource alchemy_ac97c_res[] = {
149f59c811fSManuel Lauss 	[0] = {
150f59c811fSManuel Lauss 		.start	= AU1000_AC97_PHYS_ADDR,
151f59c811fSManuel Lauss 		.end	= AU1000_AC97_PHYS_ADDR + 0xfff,
152f59c811fSManuel Lauss 		.flags	= IORESOURCE_MEM,
153f59c811fSManuel Lauss 	},
154f59c811fSManuel Lauss 	[1] = {
155f59c811fSManuel Lauss 		.start	= DMA_ID_AC97C_TX,
156f59c811fSManuel Lauss 		.end	= DMA_ID_AC97C_TX,
157f59c811fSManuel Lauss 		.flags	= IORESOURCE_DMA,
158f59c811fSManuel Lauss 	},
159f59c811fSManuel Lauss 	[2] = {
160f59c811fSManuel Lauss 		.start	= DMA_ID_AC97C_RX,
161f59c811fSManuel Lauss 		.end	= DMA_ID_AC97C_RX,
162f59c811fSManuel Lauss 		.flags	= IORESOURCE_DMA,
163f59c811fSManuel Lauss 	},
164f59c811fSManuel Lauss };
165f59c811fSManuel Lauss 
166f59c811fSManuel Lauss static struct platform_device alchemy_ac97c_dev = {
167f59c811fSManuel Lauss 	.name		= "alchemy-ac97c",
168f59c811fSManuel Lauss 	.id		= -1,
169f59c811fSManuel Lauss 	.resource	= alchemy_ac97c_res,
170f59c811fSManuel Lauss 	.num_resources	= ARRAY_SIZE(alchemy_ac97c_res),
171f59c811fSManuel Lauss };
172f59c811fSManuel Lauss 
173f59c811fSManuel Lauss static struct platform_device alchemy_ac97c_dma_dev = {
174f59c811fSManuel Lauss 	.name		= "alchemy-pcm-dma",
175f59c811fSManuel Lauss 	.id		= 0,
176f59c811fSManuel Lauss };
177f59c811fSManuel Lauss 
178f59c811fSManuel Lauss static struct platform_device db1x00_codec_dev = {
179f59c811fSManuel Lauss 	.name		= "ac97-codec",
180f59c811fSManuel Lauss 	.id		= -1,
181f59c811fSManuel Lauss };
182f59c811fSManuel Lauss 
183f59c811fSManuel Lauss static struct platform_device db1x00_audio_dev = {
184f59c811fSManuel Lauss 	.name		= "db1000-audio",
185f59c811fSManuel Lauss };
186f59c811fSManuel Lauss 
187c9af5144SManuel Lauss /******************************************************************************/
188c9af5144SManuel Lauss 
189c9af5144SManuel Lauss static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
190c9af5144SManuel Lauss {
191c9af5144SManuel Lauss 	void (*mmc_cd)(struct mmc_host *, unsigned long);
192c9af5144SManuel Lauss 	/* link against CONFIG_MMC=m */
193c9af5144SManuel Lauss 	mmc_cd = symbol_get(mmc_detect_change);
194c9af5144SManuel Lauss 	mmc_cd(ptr, msecs_to_jiffies(500));
195c9af5144SManuel Lauss 	symbol_put(mmc_detect_change);
196c9af5144SManuel Lauss 
197c9af5144SManuel Lauss 	return IRQ_HANDLED;
198c9af5144SManuel Lauss }
199c9af5144SManuel Lauss 
200c9af5144SManuel Lauss static int db1100_mmc_cd_setup(void *mmc_host, int en)
201c9af5144SManuel Lauss {
202c9af5144SManuel Lauss 	int ret = 0;
203c9af5144SManuel Lauss 
204c9af5144SManuel Lauss 	if (en) {
205c9af5144SManuel Lauss 		irq_set_irq_type(AU1100_GPIO19_INT, IRQ_TYPE_EDGE_BOTH);
206c9af5144SManuel Lauss 		ret = request_irq(AU1100_GPIO19_INT, db1100_mmc_cd, 0,
207c9af5144SManuel Lauss 				  "sd0_cd", mmc_host);
208c9af5144SManuel Lauss 	} else
209c9af5144SManuel Lauss 		free_irq(AU1100_GPIO19_INT, mmc_host);
210c9af5144SManuel Lauss 	return ret;
211c9af5144SManuel Lauss }
212c9af5144SManuel Lauss 
213c9af5144SManuel Lauss static int db1100_mmc1_cd_setup(void *mmc_host, int en)
214c9af5144SManuel Lauss {
215c9af5144SManuel Lauss 	int ret = 0;
216c9af5144SManuel Lauss 
217c9af5144SManuel Lauss 	if (en) {
218c9af5144SManuel Lauss 		irq_set_irq_type(AU1100_GPIO20_INT, IRQ_TYPE_EDGE_BOTH);
219c9af5144SManuel Lauss 		ret = request_irq(AU1100_GPIO20_INT, db1100_mmc_cd, 0,
220c9af5144SManuel Lauss 				  "sd1_cd", mmc_host);
221c9af5144SManuel Lauss 	} else
222c9af5144SManuel Lauss 		free_irq(AU1100_GPIO20_INT, mmc_host);
223c9af5144SManuel Lauss 	return ret;
224c9af5144SManuel Lauss }
225c9af5144SManuel Lauss 
226c9af5144SManuel Lauss static int db1100_mmc_card_readonly(void *mmc_host)
227c9af5144SManuel Lauss {
228c9af5144SManuel Lauss 	/* testing suggests that this bit is inverted */
229c9af5144SManuel Lauss 	return (bcsr_read(BCSR_STATUS) & BCSR_STATUS_SD0WP) ? 0 : 1;
230c9af5144SManuel Lauss }
231c9af5144SManuel Lauss 
232c9af5144SManuel Lauss static int db1100_mmc_card_inserted(void *mmc_host)
233c9af5144SManuel Lauss {
234c9af5144SManuel Lauss 	return !alchemy_gpio_get_value(19);
235c9af5144SManuel Lauss }
236c9af5144SManuel Lauss 
237c9af5144SManuel Lauss static void db1100_mmc_set_power(void *mmc_host, int state)
238c9af5144SManuel Lauss {
239c9af5144SManuel Lauss 	if (state) {
240c9af5144SManuel Lauss 		bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_SD0PWR);
241c9af5144SManuel Lauss 		msleep(400);	/* stabilization time */
242c9af5144SManuel Lauss 	} else
243c9af5144SManuel Lauss 		bcsr_mod(BCSR_BOARD, BCSR_BOARD_SD0PWR, 0);
244c9af5144SManuel Lauss }
245c9af5144SManuel Lauss 
246c9af5144SManuel Lauss static void db1100_mmcled_set(struct led_classdev *led, enum led_brightness b)
247c9af5144SManuel Lauss {
248c9af5144SManuel Lauss 	if (b != LED_OFF)
249c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED0, 0);
250c9af5144SManuel Lauss 	else
251c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED0);
252c9af5144SManuel Lauss }
253c9af5144SManuel Lauss 
254c9af5144SManuel Lauss static struct led_classdev db1100_mmc_led = {
255c9af5144SManuel Lauss 	.brightness_set	= db1100_mmcled_set,
256c9af5144SManuel Lauss };
257c9af5144SManuel Lauss 
258c9af5144SManuel Lauss static int db1100_mmc1_card_readonly(void *mmc_host)
259c9af5144SManuel Lauss {
260c9af5144SManuel Lauss 	return (bcsr_read(BCSR_BOARD) & BCSR_BOARD_SD1WP) ? 1 : 0;
261c9af5144SManuel Lauss }
262c9af5144SManuel Lauss 
263c9af5144SManuel Lauss static int db1100_mmc1_card_inserted(void *mmc_host)
264c9af5144SManuel Lauss {
265c9af5144SManuel Lauss 	return !alchemy_gpio_get_value(20);
266c9af5144SManuel Lauss }
267c9af5144SManuel Lauss 
268c9af5144SManuel Lauss static void db1100_mmc1_set_power(void *mmc_host, int state)
269c9af5144SManuel Lauss {
270c9af5144SManuel Lauss 	if (state) {
271c9af5144SManuel Lauss 		bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_SD1PWR);
272c9af5144SManuel Lauss 		msleep(400);	/* stabilization time */
273c9af5144SManuel Lauss 	} else
274c9af5144SManuel Lauss 		bcsr_mod(BCSR_BOARD, BCSR_BOARD_SD1PWR, 0);
275c9af5144SManuel Lauss }
276c9af5144SManuel Lauss 
277c9af5144SManuel Lauss static void db1100_mmc1led_set(struct led_classdev *led, enum led_brightness b)
278c9af5144SManuel Lauss {
279c9af5144SManuel Lauss 	if (b != LED_OFF)
280c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED1, 0);
281c9af5144SManuel Lauss 	else
282c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED1);
283c9af5144SManuel Lauss }
284c9af5144SManuel Lauss 
285c9af5144SManuel Lauss static struct led_classdev db1100_mmc1_led = {
286c9af5144SManuel Lauss 	.brightness_set	= db1100_mmc1led_set,
287c9af5144SManuel Lauss };
288c9af5144SManuel Lauss 
289c9af5144SManuel Lauss static struct au1xmmc_platform_data db1100_mmc_platdata[2] = {
290c9af5144SManuel Lauss 	[0] = {
291c9af5144SManuel Lauss 		.cd_setup	= db1100_mmc_cd_setup,
292c9af5144SManuel Lauss 		.set_power	= db1100_mmc_set_power,
293c9af5144SManuel Lauss 		.card_inserted	= db1100_mmc_card_inserted,
294c9af5144SManuel Lauss 		.card_readonly	= db1100_mmc_card_readonly,
295c9af5144SManuel Lauss 		.led		= &db1100_mmc_led,
296c9af5144SManuel Lauss 	},
297c9af5144SManuel Lauss 	[1] = {
298c9af5144SManuel Lauss 		.cd_setup	= db1100_mmc1_cd_setup,
299c9af5144SManuel Lauss 		.set_power	= db1100_mmc1_set_power,
300c9af5144SManuel Lauss 		.card_inserted	= db1100_mmc1_card_inserted,
301c9af5144SManuel Lauss 		.card_readonly	= db1100_mmc1_card_readonly,
302c9af5144SManuel Lauss 		.led		= &db1100_mmc1_led,
303c9af5144SManuel Lauss 	},
304c9af5144SManuel Lauss };
305c9af5144SManuel Lauss 
306c9af5144SManuel Lauss static struct resource au1100_mmc0_resources[] = {
307c9af5144SManuel Lauss 	[0] = {
308c9af5144SManuel Lauss 		.start	= AU1100_SD0_PHYS_ADDR,
309c9af5144SManuel Lauss 		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
310c9af5144SManuel Lauss 		.flags	= IORESOURCE_MEM,
311c9af5144SManuel Lauss 	},
312c9af5144SManuel Lauss 	[1] = {
313c9af5144SManuel Lauss 		.start	= AU1100_SD_INT,
314c9af5144SManuel Lauss 		.end	= AU1100_SD_INT,
315c9af5144SManuel Lauss 		.flags	= IORESOURCE_IRQ,
316c9af5144SManuel Lauss 	},
317c9af5144SManuel Lauss 	[2] = {
318c9af5144SManuel Lauss 		.start	= DMA_ID_SD0_TX,
319c9af5144SManuel Lauss 		.end	= DMA_ID_SD0_TX,
320c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
321c9af5144SManuel Lauss 	},
322c9af5144SManuel Lauss 	[3] = {
323c9af5144SManuel Lauss 		.start	= DMA_ID_SD0_RX,
324c9af5144SManuel Lauss 		.end	= DMA_ID_SD0_RX,
325c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
326c9af5144SManuel Lauss 	}
327c9af5144SManuel Lauss };
328c9af5144SManuel Lauss 
329c9af5144SManuel Lauss static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
330c9af5144SManuel Lauss 
331c9af5144SManuel Lauss static struct platform_device db1100_mmc0_dev = {
332c9af5144SManuel Lauss 	.name		= "au1xxx-mmc",
333c9af5144SManuel Lauss 	.id		= 0,
334c9af5144SManuel Lauss 	.dev = {
335c9af5144SManuel Lauss 		.dma_mask		= &au1xxx_mmc_dmamask,
336c9af5144SManuel Lauss 		.coherent_dma_mask	= DMA_BIT_MASK(32),
337c9af5144SManuel Lauss 		.platform_data		= &db1100_mmc_platdata[0],
338c9af5144SManuel Lauss 	},
339c9af5144SManuel Lauss 	.num_resources	= ARRAY_SIZE(au1100_mmc0_resources),
340c9af5144SManuel Lauss 	.resource	= au1100_mmc0_resources,
341c9af5144SManuel Lauss };
342c9af5144SManuel Lauss 
343c9af5144SManuel Lauss static struct resource au1100_mmc1_res[] = {
344c9af5144SManuel Lauss 	[0] = {
345c9af5144SManuel Lauss 		.start	= AU1100_SD1_PHYS_ADDR,
346c9af5144SManuel Lauss 		.end	= AU1100_SD1_PHYS_ADDR + 0xfff,
347c9af5144SManuel Lauss 		.flags	= IORESOURCE_MEM,
348c9af5144SManuel Lauss 	},
349c9af5144SManuel Lauss 	[1] = {
350c9af5144SManuel Lauss 		.start	= AU1100_SD_INT,
351c9af5144SManuel Lauss 		.end	= AU1100_SD_INT,
352c9af5144SManuel Lauss 		.flags	= IORESOURCE_IRQ,
353c9af5144SManuel Lauss 	},
354c9af5144SManuel Lauss 	[2] = {
355c9af5144SManuel Lauss 		.start	= DMA_ID_SD1_TX,
356c9af5144SManuel Lauss 		.end	= DMA_ID_SD1_TX,
357c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
358c9af5144SManuel Lauss 	},
359c9af5144SManuel Lauss 	[3] = {
360c9af5144SManuel Lauss 		.start	= DMA_ID_SD1_RX,
361c9af5144SManuel Lauss 		.end	= DMA_ID_SD1_RX,
362c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
363c9af5144SManuel Lauss 	}
364c9af5144SManuel Lauss };
365c9af5144SManuel Lauss 
366c9af5144SManuel Lauss static struct platform_device db1100_mmc1_dev = {
367c9af5144SManuel Lauss 	.name		= "au1xxx-mmc",
368c9af5144SManuel Lauss 	.id		= 1,
369c9af5144SManuel Lauss 	.dev = {
370c9af5144SManuel Lauss 		.dma_mask		= &au1xxx_mmc_dmamask,
371c9af5144SManuel Lauss 		.coherent_dma_mask	= DMA_BIT_MASK(32),
372c9af5144SManuel Lauss 		.platform_data		= &db1100_mmc_platdata[1],
373c9af5144SManuel Lauss 	},
374c9af5144SManuel Lauss 	.num_resources	= ARRAY_SIZE(au1100_mmc1_res),
375c9af5144SManuel Lauss 	.resource	= au1100_mmc1_res,
376c9af5144SManuel Lauss };
377c9af5144SManuel Lauss 
378e734ae13SManuel Lauss /******************************************************************************/
379e734ae13SManuel Lauss 
380e734ae13SManuel Lauss static void db1000_irda_set_phy_mode(int mode)
381e734ae13SManuel Lauss {
382e734ae13SManuel Lauss 	unsigned short mask = BCSR_RESETS_IRDA_MODE_MASK | BCSR_RESETS_FIR_SEL;
383e734ae13SManuel Lauss 
384e734ae13SManuel Lauss 	switch (mode) {
385e734ae13SManuel Lauss 	case AU1000_IRDA_PHY_MODE_OFF:
386e734ae13SManuel Lauss 		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_OFF);
387e734ae13SManuel Lauss 		break;
388e734ae13SManuel Lauss 	case AU1000_IRDA_PHY_MODE_SIR:
389e734ae13SManuel Lauss 		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_FULL);
390e734ae13SManuel Lauss 		break;
391e734ae13SManuel Lauss 	case AU1000_IRDA_PHY_MODE_FIR:
392e734ae13SManuel Lauss 		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_FULL |
393e734ae13SManuel Lauss 					    BCSR_RESETS_FIR_SEL);
394e734ae13SManuel Lauss 		break;
395e734ae13SManuel Lauss 	}
396e734ae13SManuel Lauss }
397e734ae13SManuel Lauss 
398e734ae13SManuel Lauss static struct au1k_irda_platform_data db1000_irda_platdata = {
399e734ae13SManuel Lauss 	.set_phy_mode	= db1000_irda_set_phy_mode,
400e734ae13SManuel Lauss };
401e734ae13SManuel Lauss 
402e734ae13SManuel Lauss static struct resource au1000_irda_res[] = {
403e734ae13SManuel Lauss 	[0] = {
404e734ae13SManuel Lauss 		.start	= AU1000_IRDA_PHYS_ADDR,
405e734ae13SManuel Lauss 		.end	= AU1000_IRDA_PHYS_ADDR + 0x0fff,
406e734ae13SManuel Lauss 		.flags	= IORESOURCE_MEM,
407e734ae13SManuel Lauss 	},
408e734ae13SManuel Lauss 	[1] = {
409e734ae13SManuel Lauss 		.start	= AU1000_IRDA_TX_INT,
410e734ae13SManuel Lauss 		.end	= AU1000_IRDA_TX_INT,
411e734ae13SManuel Lauss 		.flags	= IORESOURCE_IRQ,
412e734ae13SManuel Lauss 	},
413e734ae13SManuel Lauss 	[2] = {
414e734ae13SManuel Lauss 		.start	= AU1000_IRDA_RX_INT,
415e734ae13SManuel Lauss 		.end	= AU1000_IRDA_RX_INT,
416e734ae13SManuel Lauss 		.flags	= IORESOURCE_IRQ,
417e734ae13SManuel Lauss 	},
418e734ae13SManuel Lauss };
419e734ae13SManuel Lauss 
420e734ae13SManuel Lauss static struct platform_device db1000_irda_dev = {
421e734ae13SManuel Lauss 	.name	= "au1000-irda",
422e734ae13SManuel Lauss 	.id	= -1,
423e734ae13SManuel Lauss 	.dev	= {
424e734ae13SManuel Lauss 		.platform_data = &db1000_irda_platdata,
425e734ae13SManuel Lauss 	},
426e734ae13SManuel Lauss 	.resource	= au1000_irda_res,
427e734ae13SManuel Lauss 	.num_resources	= ARRAY_SIZE(au1000_irda_res),
428e734ae13SManuel Lauss };
429c9af5144SManuel Lauss 
4302a32daf1SManuel Lauss /******************************************************************************/
4312a32daf1SManuel Lauss 
4322a32daf1SManuel Lauss static struct ads7846_platform_data db1100_touch_pd = {
4332a32daf1SManuel Lauss 	.model		= 7846,
4342a32daf1SManuel Lauss 	.vref_mv	= 3300,
4352a32daf1SManuel Lauss 	.gpio_pendown	= 21,
4362a32daf1SManuel Lauss };
4372a32daf1SManuel Lauss 
4382a32daf1SManuel Lauss static struct spi_gpio_platform_data db1100_spictl_pd = {
4392a32daf1SManuel Lauss 	.sck		= 209,
4402a32daf1SManuel Lauss 	.mosi		= 208,
4412a32daf1SManuel Lauss 	.miso		= 207,
4422a32daf1SManuel Lauss 	.num_chipselect = 1,
4432a32daf1SManuel Lauss };
4442a32daf1SManuel Lauss 
4452a32daf1SManuel Lauss static struct spi_board_info db1100_spi_info[] __initdata = {
4462a32daf1SManuel Lauss 	[0] = {
4472a32daf1SManuel Lauss 		.modalias	 = "ads7846",
4482a32daf1SManuel Lauss 		.max_speed_hz	 = 3250000,
4492a32daf1SManuel Lauss 		.bus_num	 = 0,
4502a32daf1SManuel Lauss 		.chip_select	 = 0,
4512a32daf1SManuel Lauss 		.mode		 = 0,
4522a32daf1SManuel Lauss 		.irq		 = AU1100_GPIO21_INT,
4532a32daf1SManuel Lauss 		.platform_data	 = &db1100_touch_pd,
4542a32daf1SManuel Lauss 		.controller_data = (void *)210,	/* for spi_gpio: CS# GPIO210 */
4552a32daf1SManuel Lauss 	},
4562a32daf1SManuel Lauss };
4572a32daf1SManuel Lauss 
4582a32daf1SManuel Lauss static struct platform_device db1100_spi_dev = {
4592a32daf1SManuel Lauss 	.name		= "spi_gpio",
4602a32daf1SManuel Lauss 	.id		= 0,
4612a32daf1SManuel Lauss 	.dev		= {
4622a32daf1SManuel Lauss 		.platform_data	= &db1100_spictl_pd,
4632a32daf1SManuel Lauss 	},
4642a32daf1SManuel Lauss };
4652a32daf1SManuel Lauss 
4662a32daf1SManuel Lauss 
467f59c811fSManuel Lauss static struct platform_device *db1x00_devs[] = {
468f59c811fSManuel Lauss 	&db1x00_codec_dev,
469f59c811fSManuel Lauss 	&alchemy_ac97c_dma_dev,
470f59c811fSManuel Lauss 	&alchemy_ac97c_dev,
471f59c811fSManuel Lauss 	&db1x00_audio_dev,
472f59c811fSManuel Lauss };
473f59c811fSManuel Lauss 
474e734ae13SManuel Lauss static struct platform_device *db1000_devs[] = {
475e734ae13SManuel Lauss 	&db1000_irda_dev,
476e734ae13SManuel Lauss };
477e734ae13SManuel Lauss 
478f59c811fSManuel Lauss static struct platform_device *db1100_devs[] = {
479f59c811fSManuel Lauss 	&au1100_lcd_device,
480c9af5144SManuel Lauss 	&db1100_mmc0_dev,
481c9af5144SManuel Lauss 	&db1100_mmc1_dev,
482e734ae13SManuel Lauss 	&db1000_irda_dev,
4832a32daf1SManuel Lauss 	&db1100_spi_dev,
484f59c811fSManuel Lauss };
485f59c811fSManuel Lauss 
486f59c811fSManuel Lauss static int __init db1000_dev_init(void)
487f59c811fSManuel Lauss {
488f59c811fSManuel Lauss 	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
489f59c811fSManuel Lauss 	int c0, c1, d0, d1, s0, s1;
4902a32daf1SManuel Lauss 	unsigned long pfc;
491f59c811fSManuel Lauss 
492f59c811fSManuel Lauss 	if (board == BCSR_WHOAMI_DB1500) {
493f59c811fSManuel Lauss 		c0 = AU1500_GPIO2_INT;
494f59c811fSManuel Lauss 		c1 = AU1500_GPIO5_INT;
495f59c811fSManuel Lauss 		d0 = AU1500_GPIO0_INT;
496f59c811fSManuel Lauss 		d1 = AU1500_GPIO3_INT;
497f59c811fSManuel Lauss 		s0 = AU1500_GPIO1_INT;
498f59c811fSManuel Lauss 		s1 = AU1500_GPIO4_INT;
499f59c811fSManuel Lauss 	} else if (board == BCSR_WHOAMI_DB1100) {
500f59c811fSManuel Lauss 		c0 = AU1100_GPIO2_INT;
501f59c811fSManuel Lauss 		c1 = AU1100_GPIO5_INT;
502f59c811fSManuel Lauss 		d0 = AU1100_GPIO0_INT;
503f59c811fSManuel Lauss 		d1 = AU1100_GPIO3_INT;
504f59c811fSManuel Lauss 		s0 = AU1100_GPIO1_INT;
505f59c811fSManuel Lauss 		s1 = AU1100_GPIO4_INT;
506c9af5144SManuel Lauss 
507c9af5144SManuel Lauss 		gpio_direction_input(19);	/* sd0 cd# */
508c9af5144SManuel Lauss 		gpio_direction_input(20);	/* sd1 cd# */
5092a32daf1SManuel Lauss 		gpio_direction_input(21);	/* touch pendown# */
5102a32daf1SManuel Lauss 		gpio_direction_input(207);	/* SPI MISO */
5112a32daf1SManuel Lauss 		gpio_direction_output(208, 0);	/* SPI MOSI */
5122a32daf1SManuel Lauss 		gpio_direction_output(209, 1);	/* SPI SCK */
5132a32daf1SManuel Lauss 		gpio_direction_output(210, 1);	/* SPI CS# */
5142a32daf1SManuel Lauss 
5152a32daf1SManuel Lauss 		/* spi_gpio on SSI0 pins */
5162a32daf1SManuel Lauss 		pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
5172a32daf1SManuel Lauss 		pfc |= (1 << 0);	/* SSI0 pins as GPIOs */
5182a32daf1SManuel Lauss 		__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
5192a32daf1SManuel Lauss 		wmb();
5202a32daf1SManuel Lauss 
5212a32daf1SManuel Lauss 		spi_register_board_info(db1100_spi_info,
5222a32daf1SManuel Lauss 					ARRAY_SIZE(db1100_spi_info));
523c9af5144SManuel Lauss 
524f59c811fSManuel Lauss 		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
525f59c811fSManuel Lauss 	} else if (board == BCSR_WHOAMI_DB1000) {
526f59c811fSManuel Lauss 		c0 = AU1000_GPIO2_INT;
527f59c811fSManuel Lauss 		c1 = AU1000_GPIO5_INT;
528f59c811fSManuel Lauss 		d0 = AU1000_GPIO0_INT;
529f59c811fSManuel Lauss 		d1 = AU1000_GPIO3_INT;
530f59c811fSManuel Lauss 		s0 = AU1000_GPIO1_INT;
531f59c811fSManuel Lauss 		s1 = AU1000_GPIO4_INT;
532e734ae13SManuel Lauss 		platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs));
533f59c811fSManuel Lauss 	} else
534f59c811fSManuel Lauss 		return 0; /* unknown board, no further dev setup to do */
535f59c811fSManuel Lauss 
536f59c811fSManuel Lauss 	irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH);
537f59c811fSManuel Lauss 	irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH);
538f59c811fSManuel Lauss 	irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
539f59c811fSManuel Lauss 	irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
540f59c811fSManuel Lauss 	irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
541f59c811fSManuel Lauss 	irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);
542f59c811fSManuel Lauss 
543f59c811fSManuel Lauss 	db1x_register_pcmcia_socket(
544f59c811fSManuel Lauss 		AU1000_PCMCIA_ATTR_PHYS_ADDR,
545f59c811fSManuel Lauss 		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
546f59c811fSManuel Lauss 		AU1000_PCMCIA_MEM_PHYS_ADDR,
547f59c811fSManuel Lauss 		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
548f59c811fSManuel Lauss 		AU1000_PCMCIA_IO_PHYS_ADDR,
549f59c811fSManuel Lauss 		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
550f59c811fSManuel Lauss 		c0, d0,	/*s0*/0, 0, 0);
551f59c811fSManuel Lauss 
552f59c811fSManuel Lauss 	db1x_register_pcmcia_socket(
553f59c811fSManuel Lauss 		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
554f59c811fSManuel Lauss 		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
555f59c811fSManuel Lauss 		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
556f59c811fSManuel Lauss 		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
557f59c811fSManuel Lauss 		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
558f59c811fSManuel Lauss 		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
559f59c811fSManuel Lauss 		c1, d1,	/*s1*/0, 0, 1);
560f59c811fSManuel Lauss 
561f59c811fSManuel Lauss 	platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs));
562f59c811fSManuel Lauss 	db1x_register_norflash(32 << 20, 4 /* 32bit */, F_SWAPPED);
563f59c811fSManuel Lauss 	return 0;
564f59c811fSManuel Lauss }
565f59c811fSManuel Lauss device_initcall(db1000_dev_init);
566