1f59c811fSManuel Lauss /*
2851d4f5dSManuel Lauss  * DBAu1000/1500/1100 PBAu1100/1500 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 
44970e268dSManuel Lauss const char *get_system_type(void);
45f59c811fSManuel Lauss 
46970e268dSManuel Lauss int __init db1000_board_setup(void)
47f59c811fSManuel Lauss {
48f59c811fSManuel Lauss 	/* initialize board register space */
49f59c811fSManuel Lauss 	bcsr_init(DB1000_BCSR_PHYS_ADDR,
50f59c811fSManuel Lauss 		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
51f59c811fSManuel Lauss 
52970e268dSManuel Lauss 	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
53970e268dSManuel Lauss 	case BCSR_WHOAMI_DB1000:
54970e268dSManuel Lauss 	case BCSR_WHOAMI_DB1500:
55970e268dSManuel Lauss 	case BCSR_WHOAMI_DB1100:
56970e268dSManuel Lauss 	case BCSR_WHOAMI_PB1500:
57970e268dSManuel Lauss 	case BCSR_WHOAMI_PB1500R2:
58970e268dSManuel Lauss 	case BCSR_WHOAMI_PB1100:
59970e268dSManuel Lauss 		pr_info("AMD Alchemy %s Board\n", get_system_type());
60970e268dSManuel Lauss 		return 0;
61f59c811fSManuel Lauss 	}
62970e268dSManuel Lauss 	return -ENODEV;
63970e268dSManuel Lauss }
64f59c811fSManuel Lauss 
65f59c811fSManuel Lauss static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
66f59c811fSManuel Lauss {
67f59c811fSManuel Lauss 	if ((slot < 12) || (slot > 13) || pin == 0)
68f59c811fSManuel Lauss 		return -1;
69f59c811fSManuel Lauss 	if (slot == 12)
70f59c811fSManuel Lauss 		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
71f59c811fSManuel Lauss 	if (slot == 13) {
72f59c811fSManuel Lauss 		switch (pin) {
73f59c811fSManuel Lauss 		case 1: return AU1500_PCI_INTA;
74f59c811fSManuel Lauss 		case 2: return AU1500_PCI_INTB;
75f59c811fSManuel Lauss 		case 3: return AU1500_PCI_INTC;
76f59c811fSManuel Lauss 		case 4: return AU1500_PCI_INTD;
77f59c811fSManuel Lauss 		}
78f59c811fSManuel Lauss 	}
79f59c811fSManuel Lauss 	return -1;
80f59c811fSManuel Lauss }
81f59c811fSManuel Lauss 
82f59c811fSManuel Lauss static struct resource alchemy_pci_host_res[] = {
83f59c811fSManuel Lauss 	[0] = {
84f59c811fSManuel Lauss 		.start	= AU1500_PCI_PHYS_ADDR,
85f59c811fSManuel Lauss 		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
86f59c811fSManuel Lauss 		.flags	= IORESOURCE_MEM,
87f59c811fSManuel Lauss 	},
88f59c811fSManuel Lauss };
89f59c811fSManuel Lauss 
90f59c811fSManuel Lauss static struct alchemy_pci_platdata db1500_pci_pd = {
91f59c811fSManuel Lauss 	.board_map_irq	= db1500_map_pci_irq,
92f59c811fSManuel Lauss };
93f59c811fSManuel Lauss 
94f59c811fSManuel Lauss static struct platform_device db1500_pci_host_dev = {
95f59c811fSManuel Lauss 	.dev.platform_data = &db1500_pci_pd,
96f59c811fSManuel Lauss 	.name		= "alchemy-pci",
97f59c811fSManuel Lauss 	.id		= 0,
98f59c811fSManuel Lauss 	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
99f59c811fSManuel Lauss 	.resource	= alchemy_pci_host_res,
100f59c811fSManuel Lauss };
101f59c811fSManuel Lauss 
102970e268dSManuel Lauss int __init db1500_pci_setup(void)
103f59c811fSManuel Lauss {
104f59c811fSManuel Lauss 	return platform_device_register(&db1500_pci_host_dev);
105f59c811fSManuel Lauss }
106f59c811fSManuel Lauss 
107f59c811fSManuel Lauss static struct resource au1100_lcd_resources[] = {
108f59c811fSManuel Lauss 	[0] = {
109f59c811fSManuel Lauss 		.start	= AU1100_LCD_PHYS_ADDR,
110f59c811fSManuel Lauss 		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
111f59c811fSManuel Lauss 		.flags	= IORESOURCE_MEM,
112f59c811fSManuel Lauss 	},
113f59c811fSManuel Lauss 	[1] = {
114f59c811fSManuel Lauss 		.start	= AU1100_LCD_INT,
115f59c811fSManuel Lauss 		.end	= AU1100_LCD_INT,
116f59c811fSManuel Lauss 		.flags	= IORESOURCE_IRQ,
117f59c811fSManuel Lauss 	}
118f59c811fSManuel Lauss };
119f59c811fSManuel Lauss 
120f59c811fSManuel Lauss static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
121f59c811fSManuel Lauss 
122f59c811fSManuel Lauss static struct platform_device au1100_lcd_device = {
123f59c811fSManuel Lauss 	.name		= "au1100-lcd",
124f59c811fSManuel Lauss 	.id		= 0,
125f59c811fSManuel Lauss 	.dev = {
126f59c811fSManuel Lauss 		.dma_mask		= &au1100_lcd_dmamask,
127f59c811fSManuel Lauss 		.coherent_dma_mask	= DMA_BIT_MASK(32),
128f59c811fSManuel Lauss 	},
129f59c811fSManuel Lauss 	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
130f59c811fSManuel Lauss 	.resource	= au1100_lcd_resources,
131f59c811fSManuel Lauss };
132f59c811fSManuel Lauss 
133f59c811fSManuel Lauss static struct resource alchemy_ac97c_res[] = {
134f59c811fSManuel Lauss 	[0] = {
135f59c811fSManuel Lauss 		.start	= AU1000_AC97_PHYS_ADDR,
136f59c811fSManuel Lauss 		.end	= AU1000_AC97_PHYS_ADDR + 0xfff,
137f59c811fSManuel Lauss 		.flags	= IORESOURCE_MEM,
138f59c811fSManuel Lauss 	},
139f59c811fSManuel Lauss 	[1] = {
140f59c811fSManuel Lauss 		.start	= DMA_ID_AC97C_TX,
141f59c811fSManuel Lauss 		.end	= DMA_ID_AC97C_TX,
142f59c811fSManuel Lauss 		.flags	= IORESOURCE_DMA,
143f59c811fSManuel Lauss 	},
144f59c811fSManuel Lauss 	[2] = {
145f59c811fSManuel Lauss 		.start	= DMA_ID_AC97C_RX,
146f59c811fSManuel Lauss 		.end	= DMA_ID_AC97C_RX,
147f59c811fSManuel Lauss 		.flags	= IORESOURCE_DMA,
148f59c811fSManuel Lauss 	},
149f59c811fSManuel Lauss };
150f59c811fSManuel Lauss 
151f59c811fSManuel Lauss static struct platform_device alchemy_ac97c_dev = {
152f59c811fSManuel Lauss 	.name		= "alchemy-ac97c",
153f59c811fSManuel Lauss 	.id		= -1,
154f59c811fSManuel Lauss 	.resource	= alchemy_ac97c_res,
155f59c811fSManuel Lauss 	.num_resources	= ARRAY_SIZE(alchemy_ac97c_res),
156f59c811fSManuel Lauss };
157f59c811fSManuel Lauss 
158f59c811fSManuel Lauss static struct platform_device alchemy_ac97c_dma_dev = {
159f59c811fSManuel Lauss 	.name		= "alchemy-pcm-dma",
160f59c811fSManuel Lauss 	.id		= 0,
161f59c811fSManuel Lauss };
162f59c811fSManuel Lauss 
163f59c811fSManuel Lauss static struct platform_device db1x00_codec_dev = {
164f59c811fSManuel Lauss 	.name		= "ac97-codec",
165f59c811fSManuel Lauss 	.id		= -1,
166f59c811fSManuel Lauss };
167f59c811fSManuel Lauss 
168f59c811fSManuel Lauss static struct platform_device db1x00_audio_dev = {
169f59c811fSManuel Lauss 	.name		= "db1000-audio",
170f59c811fSManuel Lauss };
171f59c811fSManuel Lauss 
172c9af5144SManuel Lauss /******************************************************************************/
173c9af5144SManuel Lauss 
174c9af5144SManuel Lauss static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
175c9af5144SManuel Lauss {
176c9af5144SManuel Lauss 	void (*mmc_cd)(struct mmc_host *, unsigned long);
177c9af5144SManuel Lauss 	/* link against CONFIG_MMC=m */
178c9af5144SManuel Lauss 	mmc_cd = symbol_get(mmc_detect_change);
179c9af5144SManuel Lauss 	mmc_cd(ptr, msecs_to_jiffies(500));
180c9af5144SManuel Lauss 	symbol_put(mmc_detect_change);
181c9af5144SManuel Lauss 
182c9af5144SManuel Lauss 	return IRQ_HANDLED;
183c9af5144SManuel Lauss }
184c9af5144SManuel Lauss 
185c9af5144SManuel Lauss static int db1100_mmc_cd_setup(void *mmc_host, int en)
186c9af5144SManuel Lauss {
187851d4f5dSManuel Lauss 	int ret = 0, irq;
188851d4f5dSManuel Lauss 
189851d4f5dSManuel Lauss 	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
190851d4f5dSManuel Lauss 		irq = AU1100_GPIO19_INT;
191851d4f5dSManuel Lauss 	else
192851d4f5dSManuel Lauss 		irq = AU1100_GPIO14_INT;	/* PB1100 SD0 CD# */
193c9af5144SManuel Lauss 
194c9af5144SManuel Lauss 	if (en) {
195851d4f5dSManuel Lauss 		irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
196851d4f5dSManuel Lauss 		ret = request_irq(irq, db1100_mmc_cd, 0,
197c9af5144SManuel Lauss 				  "sd0_cd", mmc_host);
198c9af5144SManuel Lauss 	} else
199851d4f5dSManuel Lauss 		free_irq(irq, mmc_host);
200c9af5144SManuel Lauss 	return ret;
201c9af5144SManuel Lauss }
202c9af5144SManuel Lauss 
203c9af5144SManuel Lauss static int db1100_mmc1_cd_setup(void *mmc_host, int en)
204c9af5144SManuel Lauss {
205851d4f5dSManuel Lauss 	int ret = 0, irq;
206851d4f5dSManuel Lauss 
207851d4f5dSManuel Lauss 	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
208851d4f5dSManuel Lauss 		irq = AU1100_GPIO20_INT;
209851d4f5dSManuel Lauss 	else
210851d4f5dSManuel Lauss 		irq = AU1100_GPIO15_INT;	/* PB1100 SD1 CD# */
211c9af5144SManuel Lauss 
212c9af5144SManuel Lauss 	if (en) {
213851d4f5dSManuel Lauss 		irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
214851d4f5dSManuel Lauss 		ret = request_irq(irq, db1100_mmc_cd, 0,
215c9af5144SManuel Lauss 				  "sd1_cd", mmc_host);
216c9af5144SManuel Lauss 	} else
217851d4f5dSManuel Lauss 		free_irq(irq, mmc_host);
218c9af5144SManuel Lauss 	return ret;
219c9af5144SManuel Lauss }
220c9af5144SManuel Lauss 
221c9af5144SManuel Lauss static int db1100_mmc_card_readonly(void *mmc_host)
222c9af5144SManuel Lauss {
223c9af5144SManuel Lauss 	/* testing suggests that this bit is inverted */
224c9af5144SManuel Lauss 	return (bcsr_read(BCSR_STATUS) & BCSR_STATUS_SD0WP) ? 0 : 1;
225c9af5144SManuel Lauss }
226c9af5144SManuel Lauss 
227c9af5144SManuel Lauss static int db1100_mmc_card_inserted(void *mmc_host)
228c9af5144SManuel Lauss {
229c9af5144SManuel Lauss 	return !alchemy_gpio_get_value(19);
230c9af5144SManuel Lauss }
231c9af5144SManuel Lauss 
232c9af5144SManuel Lauss static void db1100_mmc_set_power(void *mmc_host, int state)
233c9af5144SManuel Lauss {
234851d4f5dSManuel Lauss 	int bit;
235851d4f5dSManuel Lauss 
236851d4f5dSManuel Lauss 	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
237851d4f5dSManuel Lauss 		bit = BCSR_BOARD_SD0PWR;
238851d4f5dSManuel Lauss 	else
239851d4f5dSManuel Lauss 		bit = BCSR_BOARD_PB1100_SD0PWR;
240851d4f5dSManuel Lauss 
241c9af5144SManuel Lauss 	if (state) {
242851d4f5dSManuel Lauss 		bcsr_mod(BCSR_BOARD, 0, bit);
243c9af5144SManuel Lauss 		msleep(400);	/* stabilization time */
244c9af5144SManuel Lauss 	} else
245851d4f5dSManuel Lauss 		bcsr_mod(BCSR_BOARD, bit, 0);
246c9af5144SManuel Lauss }
247c9af5144SManuel Lauss 
248c9af5144SManuel Lauss static void db1100_mmcled_set(struct led_classdev *led, enum led_brightness b)
249c9af5144SManuel Lauss {
250c9af5144SManuel Lauss 	if (b != LED_OFF)
251c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED0, 0);
252c9af5144SManuel Lauss 	else
253c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED0);
254c9af5144SManuel Lauss }
255c9af5144SManuel Lauss 
256c9af5144SManuel Lauss static struct led_classdev db1100_mmc_led = {
257c9af5144SManuel Lauss 	.brightness_set = db1100_mmcled_set,
258c9af5144SManuel Lauss };
259c9af5144SManuel Lauss 
260c9af5144SManuel Lauss static int db1100_mmc1_card_readonly(void *mmc_host)
261c9af5144SManuel Lauss {
262c9af5144SManuel Lauss 	return (bcsr_read(BCSR_BOARD) & BCSR_BOARD_SD1WP) ? 1 : 0;
263c9af5144SManuel Lauss }
264c9af5144SManuel Lauss 
265c9af5144SManuel Lauss static int db1100_mmc1_card_inserted(void *mmc_host)
266c9af5144SManuel Lauss {
267c9af5144SManuel Lauss 	return !alchemy_gpio_get_value(20);
268c9af5144SManuel Lauss }
269c9af5144SManuel Lauss 
270c9af5144SManuel Lauss static void db1100_mmc1_set_power(void *mmc_host, int state)
271c9af5144SManuel Lauss {
272851d4f5dSManuel Lauss 	int bit;
273851d4f5dSManuel Lauss 
274851d4f5dSManuel Lauss 	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
275851d4f5dSManuel Lauss 		bit = BCSR_BOARD_SD1PWR;
276851d4f5dSManuel Lauss 	else
277851d4f5dSManuel Lauss 		bit = BCSR_BOARD_PB1100_SD1PWR;
278851d4f5dSManuel Lauss 
279c9af5144SManuel Lauss 	if (state) {
280851d4f5dSManuel Lauss 		bcsr_mod(BCSR_BOARD, 0, bit);
281c9af5144SManuel Lauss 		msleep(400);	/* stabilization time */
282c9af5144SManuel Lauss 	} else
283851d4f5dSManuel Lauss 		bcsr_mod(BCSR_BOARD, bit, 0);
284c9af5144SManuel Lauss }
285c9af5144SManuel Lauss 
286c9af5144SManuel Lauss static void db1100_mmc1led_set(struct led_classdev *led, enum led_brightness b)
287c9af5144SManuel Lauss {
288c9af5144SManuel Lauss 	if (b != LED_OFF)
289c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED1, 0);
290c9af5144SManuel Lauss 	else
291c9af5144SManuel Lauss 		bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED1);
292c9af5144SManuel Lauss }
293c9af5144SManuel Lauss 
294c9af5144SManuel Lauss static struct led_classdev db1100_mmc1_led = {
295c9af5144SManuel Lauss 	.brightness_set = db1100_mmc1led_set,
296c9af5144SManuel Lauss };
297c9af5144SManuel Lauss 
298c9af5144SManuel Lauss static struct au1xmmc_platform_data db1100_mmc_platdata[2] = {
299c9af5144SManuel Lauss 	[0] = {
300c9af5144SManuel Lauss 		.cd_setup	= db1100_mmc_cd_setup,
301c9af5144SManuel Lauss 		.set_power	= db1100_mmc_set_power,
302c9af5144SManuel Lauss 		.card_inserted	= db1100_mmc_card_inserted,
303c9af5144SManuel Lauss 		.card_readonly	= db1100_mmc_card_readonly,
304c9af5144SManuel Lauss 		.led		= &db1100_mmc_led,
305c9af5144SManuel Lauss 	},
306c9af5144SManuel Lauss 	[1] = {
307c9af5144SManuel Lauss 		.cd_setup	= db1100_mmc1_cd_setup,
308c9af5144SManuel Lauss 		.set_power	= db1100_mmc1_set_power,
309c9af5144SManuel Lauss 		.card_inserted	= db1100_mmc1_card_inserted,
310c9af5144SManuel Lauss 		.card_readonly	= db1100_mmc1_card_readonly,
311c9af5144SManuel Lauss 		.led		= &db1100_mmc1_led,
312c9af5144SManuel Lauss 	},
313c9af5144SManuel Lauss };
314c9af5144SManuel Lauss 
315c9af5144SManuel Lauss static struct resource au1100_mmc0_resources[] = {
316c9af5144SManuel Lauss 	[0] = {
317c9af5144SManuel Lauss 		.start	= AU1100_SD0_PHYS_ADDR,
318c9af5144SManuel Lauss 		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
319c9af5144SManuel Lauss 		.flags	= IORESOURCE_MEM,
320c9af5144SManuel Lauss 	},
321c9af5144SManuel Lauss 	[1] = {
322c9af5144SManuel Lauss 		.start	= AU1100_SD_INT,
323c9af5144SManuel Lauss 		.end	= AU1100_SD_INT,
324c9af5144SManuel Lauss 		.flags	= IORESOURCE_IRQ,
325c9af5144SManuel Lauss 	},
326c9af5144SManuel Lauss 	[2] = {
327c9af5144SManuel Lauss 		.start	= DMA_ID_SD0_TX,
328c9af5144SManuel Lauss 		.end	= DMA_ID_SD0_TX,
329c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
330c9af5144SManuel Lauss 	},
331c9af5144SManuel Lauss 	[3] = {
332c9af5144SManuel Lauss 		.start	= DMA_ID_SD0_RX,
333c9af5144SManuel Lauss 		.end	= DMA_ID_SD0_RX,
334c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
335c9af5144SManuel Lauss 	}
336c9af5144SManuel Lauss };
337c9af5144SManuel Lauss 
338c9af5144SManuel Lauss static u64 au1xxx_mmc_dmamask =	 DMA_BIT_MASK(32);
339c9af5144SManuel Lauss 
340c9af5144SManuel Lauss static struct platform_device db1100_mmc0_dev = {
341c9af5144SManuel Lauss 	.name		= "au1xxx-mmc",
342c9af5144SManuel Lauss 	.id		= 0,
343c9af5144SManuel Lauss 	.dev = {
344c9af5144SManuel Lauss 		.dma_mask		= &au1xxx_mmc_dmamask,
345c9af5144SManuel Lauss 		.coherent_dma_mask	= DMA_BIT_MASK(32),
346c9af5144SManuel Lauss 		.platform_data		= &db1100_mmc_platdata[0],
347c9af5144SManuel Lauss 	},
348c9af5144SManuel Lauss 	.num_resources	= ARRAY_SIZE(au1100_mmc0_resources),
349c9af5144SManuel Lauss 	.resource	= au1100_mmc0_resources,
350c9af5144SManuel Lauss };
351c9af5144SManuel Lauss 
352c9af5144SManuel Lauss static struct resource au1100_mmc1_res[] = {
353c9af5144SManuel Lauss 	[0] = {
354c9af5144SManuel Lauss 		.start	= AU1100_SD1_PHYS_ADDR,
355c9af5144SManuel Lauss 		.end	= AU1100_SD1_PHYS_ADDR + 0xfff,
356c9af5144SManuel Lauss 		.flags	= IORESOURCE_MEM,
357c9af5144SManuel Lauss 	},
358c9af5144SManuel Lauss 	[1] = {
359c9af5144SManuel Lauss 		.start	= AU1100_SD_INT,
360c9af5144SManuel Lauss 		.end	= AU1100_SD_INT,
361c9af5144SManuel Lauss 		.flags	= IORESOURCE_IRQ,
362c9af5144SManuel Lauss 	},
363c9af5144SManuel Lauss 	[2] = {
364c9af5144SManuel Lauss 		.start	= DMA_ID_SD1_TX,
365c9af5144SManuel Lauss 		.end	= DMA_ID_SD1_TX,
366c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
367c9af5144SManuel Lauss 	},
368c9af5144SManuel Lauss 	[3] = {
369c9af5144SManuel Lauss 		.start	= DMA_ID_SD1_RX,
370c9af5144SManuel Lauss 		.end	= DMA_ID_SD1_RX,
371c9af5144SManuel Lauss 		.flags	= IORESOURCE_DMA,
372c9af5144SManuel Lauss 	}
373c9af5144SManuel Lauss };
374c9af5144SManuel Lauss 
375c9af5144SManuel Lauss static struct platform_device db1100_mmc1_dev = {
376c9af5144SManuel Lauss 	.name		= "au1xxx-mmc",
377c9af5144SManuel Lauss 	.id		= 1,
378c9af5144SManuel Lauss 	.dev = {
379c9af5144SManuel Lauss 		.dma_mask		= &au1xxx_mmc_dmamask,
380c9af5144SManuel Lauss 		.coherent_dma_mask	= DMA_BIT_MASK(32),
381c9af5144SManuel Lauss 		.platform_data		= &db1100_mmc_platdata[1],
382c9af5144SManuel Lauss 	},
383c9af5144SManuel Lauss 	.num_resources	= ARRAY_SIZE(au1100_mmc1_res),
384c9af5144SManuel Lauss 	.resource	= au1100_mmc1_res,
385c9af5144SManuel Lauss };
386c9af5144SManuel Lauss 
387e734ae13SManuel Lauss /******************************************************************************/
388e734ae13SManuel Lauss 
389e734ae13SManuel Lauss static void db1000_irda_set_phy_mode(int mode)
390e734ae13SManuel Lauss {
391e734ae13SManuel Lauss 	unsigned short mask = BCSR_RESETS_IRDA_MODE_MASK | BCSR_RESETS_FIR_SEL;
392e734ae13SManuel Lauss 
393e734ae13SManuel Lauss 	switch (mode) {
394e734ae13SManuel Lauss 	case AU1000_IRDA_PHY_MODE_OFF:
395e734ae13SManuel Lauss 		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_OFF);
396e734ae13SManuel Lauss 		break;
397e734ae13SManuel Lauss 	case AU1000_IRDA_PHY_MODE_SIR:
398e734ae13SManuel Lauss 		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_FULL);
399e734ae13SManuel Lauss 		break;
400e734ae13SManuel Lauss 	case AU1000_IRDA_PHY_MODE_FIR:
401e734ae13SManuel Lauss 		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_FULL |
402e734ae13SManuel Lauss 					    BCSR_RESETS_FIR_SEL);
403e734ae13SManuel Lauss 		break;
404e734ae13SManuel Lauss 	}
405e734ae13SManuel Lauss }
406e734ae13SManuel Lauss 
407e734ae13SManuel Lauss static struct au1k_irda_platform_data db1000_irda_platdata = {
408e734ae13SManuel Lauss 	.set_phy_mode	= db1000_irda_set_phy_mode,
409e734ae13SManuel Lauss };
410e734ae13SManuel Lauss 
411e734ae13SManuel Lauss static struct resource au1000_irda_res[] = {
412e734ae13SManuel Lauss 	[0] = {
413e734ae13SManuel Lauss 		.start	= AU1000_IRDA_PHYS_ADDR,
414e734ae13SManuel Lauss 		.end	= AU1000_IRDA_PHYS_ADDR + 0x0fff,
415e734ae13SManuel Lauss 		.flags	= IORESOURCE_MEM,
416e734ae13SManuel Lauss 	},
417e734ae13SManuel Lauss 	[1] = {
418e734ae13SManuel Lauss 		.start	= AU1000_IRDA_TX_INT,
419e734ae13SManuel Lauss 		.end	= AU1000_IRDA_TX_INT,
420e734ae13SManuel Lauss 		.flags	= IORESOURCE_IRQ,
421e734ae13SManuel Lauss 	},
422e734ae13SManuel Lauss 	[2] = {
423e734ae13SManuel Lauss 		.start	= AU1000_IRDA_RX_INT,
424e734ae13SManuel Lauss 		.end	= AU1000_IRDA_RX_INT,
425e734ae13SManuel Lauss 		.flags	= IORESOURCE_IRQ,
426e734ae13SManuel Lauss 	},
427e734ae13SManuel Lauss };
428e734ae13SManuel Lauss 
429e734ae13SManuel Lauss static struct platform_device db1000_irda_dev = {
430e734ae13SManuel Lauss 	.name	= "au1000-irda",
431e734ae13SManuel Lauss 	.id	= -1,
432e734ae13SManuel Lauss 	.dev	= {
433e734ae13SManuel Lauss 		.platform_data = &db1000_irda_platdata,
434e734ae13SManuel Lauss 	},
435e734ae13SManuel Lauss 	.resource	= au1000_irda_res,
436e734ae13SManuel Lauss 	.num_resources	= ARRAY_SIZE(au1000_irda_res),
437e734ae13SManuel Lauss };
438c9af5144SManuel Lauss 
4392a32daf1SManuel Lauss /******************************************************************************/
4402a32daf1SManuel Lauss 
4412a32daf1SManuel Lauss static struct ads7846_platform_data db1100_touch_pd = {
4422a32daf1SManuel Lauss 	.model		= 7846,
4432a32daf1SManuel Lauss 	.vref_mv	= 3300,
4442a32daf1SManuel Lauss 	.gpio_pendown	= 21,
4452a32daf1SManuel Lauss };
4462a32daf1SManuel Lauss 
4472a32daf1SManuel Lauss static struct spi_gpio_platform_data db1100_spictl_pd = {
4482a32daf1SManuel Lauss 	.sck		= 209,
4492a32daf1SManuel Lauss 	.mosi		= 208,
4502a32daf1SManuel Lauss 	.miso		= 207,
4512a32daf1SManuel Lauss 	.num_chipselect = 1,
4522a32daf1SManuel Lauss };
4532a32daf1SManuel Lauss 
4542a32daf1SManuel Lauss static struct spi_board_info db1100_spi_info[] __initdata = {
4552a32daf1SManuel Lauss 	[0] = {
4562a32daf1SManuel Lauss 		.modalias	 = "ads7846",
4572a32daf1SManuel Lauss 		.max_speed_hz	 = 3250000,
4582a32daf1SManuel Lauss 		.bus_num	 = 0,
4592a32daf1SManuel Lauss 		.chip_select	 = 0,
4602a32daf1SManuel Lauss 		.mode		 = 0,
4612a32daf1SManuel Lauss 		.irq		 = AU1100_GPIO21_INT,
4622a32daf1SManuel Lauss 		.platform_data	 = &db1100_touch_pd,
4632a32daf1SManuel Lauss 		.controller_data = (void *)210, /* for spi_gpio: CS# GPIO210 */
4642a32daf1SManuel Lauss 	},
4652a32daf1SManuel Lauss };
4662a32daf1SManuel Lauss 
4672a32daf1SManuel Lauss static struct platform_device db1100_spi_dev = {
4682a32daf1SManuel Lauss 	.name		= "spi_gpio",
4692a32daf1SManuel Lauss 	.id		= 0,
4702a32daf1SManuel Lauss 	.dev		= {
4712a32daf1SManuel Lauss 		.platform_data	= &db1100_spictl_pd,
4722a32daf1SManuel Lauss 	},
4732a32daf1SManuel Lauss };
4742a32daf1SManuel Lauss 
4752a32daf1SManuel Lauss 
476f59c811fSManuel Lauss static struct platform_device *db1x00_devs[] = {
477f59c811fSManuel Lauss 	&db1x00_codec_dev,
478f59c811fSManuel Lauss 	&alchemy_ac97c_dma_dev,
479f59c811fSManuel Lauss 	&alchemy_ac97c_dev,
480f59c811fSManuel Lauss 	&db1x00_audio_dev,
481f59c811fSManuel Lauss };
482f59c811fSManuel Lauss 
483e734ae13SManuel Lauss static struct platform_device *db1000_devs[] = {
484e734ae13SManuel Lauss 	&db1000_irda_dev,
485e734ae13SManuel Lauss };
486e734ae13SManuel Lauss 
487f59c811fSManuel Lauss static struct platform_device *db1100_devs[] = {
488f59c811fSManuel Lauss 	&au1100_lcd_device,
489c9af5144SManuel Lauss 	&db1100_mmc0_dev,
490c9af5144SManuel Lauss 	&db1100_mmc1_dev,
491e734ae13SManuel Lauss 	&db1000_irda_dev,
492f59c811fSManuel Lauss };
493f59c811fSManuel Lauss 
494970e268dSManuel Lauss int __init db1000_dev_setup(void)
495f59c811fSManuel Lauss {
496f59c811fSManuel Lauss 	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
497851d4f5dSManuel Lauss 	int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
4982a32daf1SManuel Lauss 	unsigned long pfc;
499f59c811fSManuel Lauss 
500f59c811fSManuel Lauss 	if (board == BCSR_WHOAMI_DB1500) {
501f59c811fSManuel Lauss 		c0 = AU1500_GPIO2_INT;
502f59c811fSManuel Lauss 		c1 = AU1500_GPIO5_INT;
503f59c811fSManuel Lauss 		d0 = AU1500_GPIO0_INT;
504f59c811fSManuel Lauss 		d1 = AU1500_GPIO3_INT;
505f59c811fSManuel Lauss 		s0 = AU1500_GPIO1_INT;
506f59c811fSManuel Lauss 		s1 = AU1500_GPIO4_INT;
507f59c811fSManuel Lauss 	} else if (board == BCSR_WHOAMI_DB1100) {
508f59c811fSManuel Lauss 		c0 = AU1100_GPIO2_INT;
509f59c811fSManuel Lauss 		c1 = AU1100_GPIO5_INT;
510f59c811fSManuel Lauss 		d0 = AU1100_GPIO0_INT;
511f59c811fSManuel Lauss 		d1 = AU1100_GPIO3_INT;
512f59c811fSManuel Lauss 		s0 = AU1100_GPIO1_INT;
513f59c811fSManuel Lauss 		s1 = AU1100_GPIO4_INT;
514c9af5144SManuel Lauss 
5154294ad1cSManuel Lauss 		gpio_request(19, "sd0_cd");
5164294ad1cSManuel Lauss 		gpio_request(20, "sd1_cd");
517c9af5144SManuel Lauss 		gpio_direction_input(19);	/* sd0 cd# */
518c9af5144SManuel Lauss 		gpio_direction_input(20);	/* sd1 cd# */
5192a32daf1SManuel Lauss 
5202a32daf1SManuel Lauss 		/* spi_gpio on SSI0 pins */
5212a32daf1SManuel Lauss 		pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
5222a32daf1SManuel Lauss 		pfc |= (1 << 0);	/* SSI0 pins as GPIOs */
5232a32daf1SManuel Lauss 		__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
5242a32daf1SManuel Lauss 		wmb();
5252a32daf1SManuel Lauss 
5262a32daf1SManuel Lauss 		spi_register_board_info(db1100_spi_info,
5272a32daf1SManuel Lauss 					ARRAY_SIZE(db1100_spi_info));
528c9af5144SManuel Lauss 
529f59c811fSManuel Lauss 		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
530851d4f5dSManuel Lauss 		platform_device_register(&db1100_spi_dev);
531f59c811fSManuel Lauss 	} else if (board == BCSR_WHOAMI_DB1000) {
532f59c811fSManuel Lauss 		c0 = AU1000_GPIO2_INT;
533f59c811fSManuel Lauss 		c1 = AU1000_GPIO5_INT;
534f59c811fSManuel Lauss 		d0 = AU1000_GPIO0_INT;
535f59c811fSManuel Lauss 		d1 = AU1000_GPIO3_INT;
536f59c811fSManuel Lauss 		s0 = AU1000_GPIO1_INT;
537f59c811fSManuel Lauss 		s1 = AU1000_GPIO4_INT;
538e734ae13SManuel Lauss 		platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs));
539851d4f5dSManuel Lauss 	} else if ((board == BCSR_WHOAMI_PB1500) ||
540851d4f5dSManuel Lauss 		   (board == BCSR_WHOAMI_PB1500R2)) {
541851d4f5dSManuel Lauss 		c0 = AU1500_GPIO203_INT;
542851d4f5dSManuel Lauss 		d0 = AU1500_GPIO201_INT;
543851d4f5dSManuel Lauss 		s0 = AU1500_GPIO202_INT;
544851d4f5dSManuel Lauss 		twosocks = 0;
545851d4f5dSManuel Lauss 		flashsize = 64;
546851d4f5dSManuel Lauss 		/* RTC and daughtercard irqs */
547851d4f5dSManuel Lauss 		irq_set_irq_type(AU1500_GPIO204_INT, IRQ_TYPE_LEVEL_LOW);
548851d4f5dSManuel Lauss 		irq_set_irq_type(AU1500_GPIO205_INT, IRQ_TYPE_LEVEL_LOW);
549851d4f5dSManuel Lauss 		/* EPSON S1D13806 0x1b000000
550851d4f5dSManuel Lauss 		 * SRAM 1MB/2MB	  0x1a000000
551851d4f5dSManuel Lauss 		 * DS1693 RTC	  0x0c000000
552851d4f5dSManuel Lauss 		 */
553851d4f5dSManuel Lauss 	} else if (board == BCSR_WHOAMI_PB1100) {
554851d4f5dSManuel Lauss 		c0 = AU1100_GPIO11_INT;
555851d4f5dSManuel Lauss 		d0 = AU1100_GPIO9_INT;
556851d4f5dSManuel Lauss 		s0 = AU1100_GPIO10_INT;
557851d4f5dSManuel Lauss 		twosocks = 0;
558851d4f5dSManuel Lauss 		flashsize = 64;
559851d4f5dSManuel Lauss 		/* pendown, rtc, daughtercard irqs */
560851d4f5dSManuel Lauss 		irq_set_irq_type(AU1100_GPIO8_INT, IRQ_TYPE_LEVEL_LOW);
561851d4f5dSManuel Lauss 		irq_set_irq_type(AU1100_GPIO12_INT, IRQ_TYPE_LEVEL_LOW);
562851d4f5dSManuel Lauss 		irq_set_irq_type(AU1100_GPIO13_INT, IRQ_TYPE_LEVEL_LOW);
563851d4f5dSManuel Lauss 		/* EPSON S1D13806 0x1b000000
564851d4f5dSManuel Lauss 		 * SRAM 1MB/2MB	  0x1a000000
565851d4f5dSManuel Lauss 		 * DiskOnChip	  0x0d000000
566851d4f5dSManuel Lauss 		 * DS1693 RTC	  0x0c000000
567851d4f5dSManuel Lauss 		 */
568851d4f5dSManuel Lauss 		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
569f59c811fSManuel Lauss 	} else
570f59c811fSManuel Lauss 		return 0; /* unknown board, no further dev setup to do */
571f59c811fSManuel Lauss 
572f59c811fSManuel Lauss 	irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH);
573f59c811fSManuel Lauss 	irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
574f59c811fSManuel Lauss 	irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
575f59c811fSManuel Lauss 
576f59c811fSManuel Lauss 	db1x_register_pcmcia_socket(
577f59c811fSManuel Lauss 		AU1000_PCMCIA_ATTR_PHYS_ADDR,
578f59c811fSManuel Lauss 		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
579f59c811fSManuel Lauss 		AU1000_PCMCIA_MEM_PHYS_ADDR,
580f59c811fSManuel Lauss 		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
581f59c811fSManuel Lauss 		AU1000_PCMCIA_IO_PHYS_ADDR,
582f59c811fSManuel Lauss 		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
583f59c811fSManuel Lauss 		c0, d0, /*s0*/0, 0, 0);
584f59c811fSManuel Lauss 
585851d4f5dSManuel Lauss 	if (twosocks) {
586851d4f5dSManuel Lauss 		irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH);
587851d4f5dSManuel Lauss 		irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
588851d4f5dSManuel Lauss 		irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);
589851d4f5dSManuel Lauss 
590f59c811fSManuel Lauss 		db1x_register_pcmcia_socket(
591f59c811fSManuel Lauss 			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
592f59c811fSManuel Lauss 			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
593f59c811fSManuel Lauss 			AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
594f59c811fSManuel Lauss 			AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
595f59c811fSManuel Lauss 			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
596f59c811fSManuel Lauss 			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
597f59c811fSManuel Lauss 			c1, d1, /*s1*/0, 0, 1);
598851d4f5dSManuel Lauss 	}
599f59c811fSManuel Lauss 
600f59c811fSManuel Lauss 	platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs));
601851d4f5dSManuel Lauss 	db1x_register_norflash(flashsize << 20, 4 /* 32bit */, F_SWAPPED);
602f59c811fSManuel Lauss 	return 0;
603f59c811fSManuel Lauss }
604