1/*
2 * DBAu1000/1500/1100 PBAu1100/1500 board support
3 *
4 * Copyright 2000, 2008 MontaVista Software Inc.
5 * Author: MontaVista Software, Inc. <source@mvista.com>
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 as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22#include <linux/clk.h>
23#include <linux/dma-mapping.h>
24#include <linux/gpio.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/leds.h>
28#include <linux/mmc/host.h>
29#include <linux/module.h>
30#include <linux/platform_device.h>
31#include <linux/pm.h>
32#include <linux/spi/spi.h>
33#include <linux/spi/spi_gpio.h>
34#include <linux/spi/ads7846.h>
35#include <asm/mach-au1x00/au1000.h>
36#include <asm/mach-au1x00/au1000_dma.h>
37#include <asm/mach-au1x00/au1100_mmc.h>
38#include <asm/mach-db1x00/bcsr.h>
39#include <asm/reboot.h>
40#include <prom.h>
41#include "platform.h"
42
43#define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT)
44
45const char *get_system_type(void);
46
47int __init db1000_board_setup(void)
48{
49	/* initialize board register space */
50	bcsr_init(DB1000_BCSR_PHYS_ADDR,
51		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
52
53	switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
54	case BCSR_WHOAMI_DB1000:
55	case BCSR_WHOAMI_DB1500:
56	case BCSR_WHOAMI_DB1100:
57	case BCSR_WHOAMI_PB1500:
58	case BCSR_WHOAMI_PB1500R2:
59	case BCSR_WHOAMI_PB1100:
60		pr_info("AMD Alchemy %s Board\n", get_system_type());
61		return 0;
62	}
63	return -ENODEV;
64}
65
66static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
67{
68	if ((slot < 12) || (slot > 13) || pin == 0)
69		return -1;
70	if (slot == 12)
71		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
72	if (slot == 13) {
73		switch (pin) {
74		case 1: return AU1500_PCI_INTA;
75		case 2: return AU1500_PCI_INTB;
76		case 3: return AU1500_PCI_INTC;
77		case 4: return AU1500_PCI_INTD;
78		}
79	}
80	return -1;
81}
82
83static struct resource alchemy_pci_host_res[] = {
84	[0] = {
85		.start	= AU1500_PCI_PHYS_ADDR,
86		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
87		.flags	= IORESOURCE_MEM,
88	},
89};
90
91static struct alchemy_pci_platdata db1500_pci_pd = {
92	.board_map_irq	= db1500_map_pci_irq,
93};
94
95static struct platform_device db1500_pci_host_dev = {
96	.dev.platform_data = &db1500_pci_pd,
97	.name		= "alchemy-pci",
98	.id		= 0,
99	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
100	.resource	= alchemy_pci_host_res,
101};
102
103int __init db1500_pci_setup(void)
104{
105	return platform_device_register(&db1500_pci_host_dev);
106}
107
108static struct resource au1100_lcd_resources[] = {
109	[0] = {
110		.start	= AU1100_LCD_PHYS_ADDR,
111		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
112		.flags	= IORESOURCE_MEM,
113	},
114	[1] = {
115		.start	= AU1100_LCD_INT,
116		.end	= AU1100_LCD_INT,
117		.flags	= IORESOURCE_IRQ,
118	}
119};
120
121static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
122
123static struct platform_device au1100_lcd_device = {
124	.name		= "au1100-lcd",
125	.id		= 0,
126	.dev = {
127		.dma_mask		= &au1100_lcd_dmamask,
128		.coherent_dma_mask	= DMA_BIT_MASK(32),
129	},
130	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
131	.resource	= au1100_lcd_resources,
132};
133
134static struct resource alchemy_ac97c_res[] = {
135	[0] = {
136		.start	= AU1000_AC97_PHYS_ADDR,
137		.end	= AU1000_AC97_PHYS_ADDR + 0xfff,
138		.flags	= IORESOURCE_MEM,
139	},
140	[1] = {
141		.start	= DMA_ID_AC97C_TX,
142		.end	= DMA_ID_AC97C_TX,
143		.flags	= IORESOURCE_DMA,
144	},
145	[2] = {
146		.start	= DMA_ID_AC97C_RX,
147		.end	= DMA_ID_AC97C_RX,
148		.flags	= IORESOURCE_DMA,
149	},
150};
151
152static struct platform_device alchemy_ac97c_dev = {
153	.name		= "alchemy-ac97c",
154	.id		= -1,
155	.resource	= alchemy_ac97c_res,
156	.num_resources	= ARRAY_SIZE(alchemy_ac97c_res),
157};
158
159static struct platform_device alchemy_ac97c_dma_dev = {
160	.name		= "alchemy-pcm-dma",
161	.id		= 0,
162};
163
164static struct platform_device db1x00_codec_dev = {
165	.name		= "ac97-codec",
166	.id		= -1,
167};
168
169static struct platform_device db1x00_audio_dev = {
170	.name		= "db1000-audio",
171};
172
173/******************************************************************************/
174
175static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
176{
177	void (*mmc_cd)(struct mmc_host *, unsigned long);
178	/* link against CONFIG_MMC=m */
179	mmc_cd = symbol_get(mmc_detect_change);
180	mmc_cd(ptr, msecs_to_jiffies(500));
181	symbol_put(mmc_detect_change);
182
183	return IRQ_HANDLED;
184}
185
186static int db1100_mmc_cd_setup(void *mmc_host, int en)
187{
188	int ret = 0, irq;
189
190	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
191		irq = AU1100_GPIO19_INT;
192	else
193		irq = AU1100_GPIO14_INT;	/* PB1100 SD0 CD# */
194
195	if (en) {
196		irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
197		ret = request_irq(irq, db1100_mmc_cd, 0,
198				  "sd0_cd", mmc_host);
199	} else
200		free_irq(irq, mmc_host);
201	return ret;
202}
203
204static int db1100_mmc1_cd_setup(void *mmc_host, int en)
205{
206	int ret = 0, irq;
207
208	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
209		irq = AU1100_GPIO20_INT;
210	else
211		irq = AU1100_GPIO15_INT;	/* PB1100 SD1 CD# */
212
213	if (en) {
214		irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
215		ret = request_irq(irq, db1100_mmc_cd, 0,
216				  "sd1_cd", mmc_host);
217	} else
218		free_irq(irq, mmc_host);
219	return ret;
220}
221
222static int db1100_mmc_card_readonly(void *mmc_host)
223{
224	/* testing suggests that this bit is inverted */
225	return (bcsr_read(BCSR_STATUS) & BCSR_STATUS_SD0WP) ? 0 : 1;
226}
227
228static int db1100_mmc_card_inserted(void *mmc_host)
229{
230	return !alchemy_gpio_get_value(19);
231}
232
233static void db1100_mmc_set_power(void *mmc_host, int state)
234{
235	int bit;
236
237	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
238		bit = BCSR_BOARD_SD0PWR;
239	else
240		bit = BCSR_BOARD_PB1100_SD0PWR;
241
242	if (state) {
243		bcsr_mod(BCSR_BOARD, 0, bit);
244		msleep(400);	/* stabilization time */
245	} else
246		bcsr_mod(BCSR_BOARD, bit, 0);
247}
248
249static void db1100_mmcled_set(struct led_classdev *led, enum led_brightness b)
250{
251	if (b != LED_OFF)
252		bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED0, 0);
253	else
254		bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED0);
255}
256
257static struct led_classdev db1100_mmc_led = {
258	.brightness_set = db1100_mmcled_set,
259};
260
261static int db1100_mmc1_card_readonly(void *mmc_host)
262{
263	return (bcsr_read(BCSR_BOARD) & BCSR_BOARD_SD1WP) ? 1 : 0;
264}
265
266static int db1100_mmc1_card_inserted(void *mmc_host)
267{
268	return !alchemy_gpio_get_value(20);
269}
270
271static void db1100_mmc1_set_power(void *mmc_host, int state)
272{
273	int bit;
274
275	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
276		bit = BCSR_BOARD_SD1PWR;
277	else
278		bit = BCSR_BOARD_PB1100_SD1PWR;
279
280	if (state) {
281		bcsr_mod(BCSR_BOARD, 0, bit);
282		msleep(400);	/* stabilization time */
283	} else
284		bcsr_mod(BCSR_BOARD, bit, 0);
285}
286
287static void db1100_mmc1led_set(struct led_classdev *led, enum led_brightness b)
288{
289	if (b != LED_OFF)
290		bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED1, 0);
291	else
292		bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED1);
293}
294
295static struct led_classdev db1100_mmc1_led = {
296	.brightness_set = db1100_mmc1led_set,
297};
298
299static struct au1xmmc_platform_data db1100_mmc_platdata[2] = {
300	[0] = {
301		.cd_setup	= db1100_mmc_cd_setup,
302		.set_power	= db1100_mmc_set_power,
303		.card_inserted	= db1100_mmc_card_inserted,
304		.card_readonly	= db1100_mmc_card_readonly,
305		.led		= &db1100_mmc_led,
306	},
307	[1] = {
308		.cd_setup	= db1100_mmc1_cd_setup,
309		.set_power	= db1100_mmc1_set_power,
310		.card_inserted	= db1100_mmc1_card_inserted,
311		.card_readonly	= db1100_mmc1_card_readonly,
312		.led		= &db1100_mmc1_led,
313	},
314};
315
316static struct resource au1100_mmc0_resources[] = {
317	[0] = {
318		.start	= AU1100_SD0_PHYS_ADDR,
319		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
320		.flags	= IORESOURCE_MEM,
321	},
322	[1] = {
323		.start	= AU1100_SD_INT,
324		.end	= AU1100_SD_INT,
325		.flags	= IORESOURCE_IRQ,
326	},
327	[2] = {
328		.start	= DMA_ID_SD0_TX,
329		.end	= DMA_ID_SD0_TX,
330		.flags	= IORESOURCE_DMA,
331	},
332	[3] = {
333		.start	= DMA_ID_SD0_RX,
334		.end	= DMA_ID_SD0_RX,
335		.flags	= IORESOURCE_DMA,
336	}
337};
338
339static u64 au1xxx_mmc_dmamask =	 DMA_BIT_MASK(32);
340
341static struct platform_device db1100_mmc0_dev = {
342	.name		= "au1xxx-mmc",
343	.id		= 0,
344	.dev = {
345		.dma_mask		= &au1xxx_mmc_dmamask,
346		.coherent_dma_mask	= DMA_BIT_MASK(32),
347		.platform_data		= &db1100_mmc_platdata[0],
348	},
349	.num_resources	= ARRAY_SIZE(au1100_mmc0_resources),
350	.resource	= au1100_mmc0_resources,
351};
352
353static struct resource au1100_mmc1_res[] = {
354	[0] = {
355		.start	= AU1100_SD1_PHYS_ADDR,
356		.end	= AU1100_SD1_PHYS_ADDR + 0xfff,
357		.flags	= IORESOURCE_MEM,
358	},
359	[1] = {
360		.start	= AU1100_SD_INT,
361		.end	= AU1100_SD_INT,
362		.flags	= IORESOURCE_IRQ,
363	},
364	[2] = {
365		.start	= DMA_ID_SD1_TX,
366		.end	= DMA_ID_SD1_TX,
367		.flags	= IORESOURCE_DMA,
368	},
369	[3] = {
370		.start	= DMA_ID_SD1_RX,
371		.end	= DMA_ID_SD1_RX,
372		.flags	= IORESOURCE_DMA,
373	}
374};
375
376static struct platform_device db1100_mmc1_dev = {
377	.name		= "au1xxx-mmc",
378	.id		= 1,
379	.dev = {
380		.dma_mask		= &au1xxx_mmc_dmamask,
381		.coherent_dma_mask	= DMA_BIT_MASK(32),
382		.platform_data		= &db1100_mmc_platdata[1],
383	},
384	.num_resources	= ARRAY_SIZE(au1100_mmc1_res),
385	.resource	= au1100_mmc1_res,
386};
387
388/******************************************************************************/
389
390static void db1000_irda_set_phy_mode(int mode)
391{
392	unsigned short mask = BCSR_RESETS_IRDA_MODE_MASK | BCSR_RESETS_FIR_SEL;
393
394	switch (mode) {
395	case AU1000_IRDA_PHY_MODE_OFF:
396		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_OFF);
397		break;
398	case AU1000_IRDA_PHY_MODE_SIR:
399		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_FULL);
400		break;
401	case AU1000_IRDA_PHY_MODE_FIR:
402		bcsr_mod(BCSR_RESETS, mask, BCSR_RESETS_IRDA_MODE_FULL |
403					    BCSR_RESETS_FIR_SEL);
404		break;
405	}
406}
407
408static struct au1k_irda_platform_data db1000_irda_platdata = {
409	.set_phy_mode	= db1000_irda_set_phy_mode,
410};
411
412static struct resource au1000_irda_res[] = {
413	[0] = {
414		.start	= AU1000_IRDA_PHYS_ADDR,
415		.end	= AU1000_IRDA_PHYS_ADDR + 0x0fff,
416		.flags	= IORESOURCE_MEM,
417	},
418	[1] = {
419		.start	= AU1000_IRDA_TX_INT,
420		.end	= AU1000_IRDA_TX_INT,
421		.flags	= IORESOURCE_IRQ,
422	},
423	[2] = {
424		.start	= AU1000_IRDA_RX_INT,
425		.end	= AU1000_IRDA_RX_INT,
426		.flags	= IORESOURCE_IRQ,
427	},
428};
429
430static struct platform_device db1000_irda_dev = {
431	.name	= "au1000-irda",
432	.id	= -1,
433	.dev	= {
434		.platform_data = &db1000_irda_platdata,
435	},
436	.resource	= au1000_irda_res,
437	.num_resources	= ARRAY_SIZE(au1000_irda_res),
438};
439
440/******************************************************************************/
441
442static struct ads7846_platform_data db1100_touch_pd = {
443	.model		= 7846,
444	.vref_mv	= 3300,
445	.gpio_pendown	= 21,
446};
447
448static struct spi_gpio_platform_data db1100_spictl_pd = {
449	.sck		= 209,
450	.mosi		= 208,
451	.miso		= 207,
452	.num_chipselect = 1,
453};
454
455static struct spi_board_info db1100_spi_info[] __initdata = {
456	[0] = {
457		.modalias	 = "ads7846",
458		.max_speed_hz	 = 3250000,
459		.bus_num	 = 0,
460		.chip_select	 = 0,
461		.mode		 = 0,
462		.irq		 = AU1100_GPIO21_INT,
463		.platform_data	 = &db1100_touch_pd,
464		.controller_data = (void *)210, /* for spi_gpio: CS# GPIO210 */
465	},
466};
467
468static struct platform_device db1100_spi_dev = {
469	.name		= "spi_gpio",
470	.id		= 0,
471	.dev		= {
472		.platform_data	= &db1100_spictl_pd,
473	},
474};
475
476
477static struct platform_device *db1x00_devs[] = {
478	&db1x00_codec_dev,
479	&alchemy_ac97c_dma_dev,
480	&alchemy_ac97c_dev,
481	&db1x00_audio_dev,
482};
483
484static struct platform_device *db1000_devs[] = {
485	&db1000_irda_dev,
486};
487
488static struct platform_device *db1100_devs[] = {
489	&au1100_lcd_device,
490	&db1100_mmc0_dev,
491	&db1100_mmc1_dev,
492	&db1000_irda_dev,
493};
494
495int __init db1000_dev_setup(void)
496{
497	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
498	int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
499	unsigned long pfc;
500	struct clk *c, *p;
501
502	if (board == BCSR_WHOAMI_DB1500) {
503		c0 = AU1500_GPIO2_INT;
504		c1 = AU1500_GPIO5_INT;
505		d0 = AU1500_GPIO0_INT;
506		d1 = AU1500_GPIO3_INT;
507		s0 = AU1500_GPIO1_INT;
508		s1 = AU1500_GPIO4_INT;
509	} else if (board == BCSR_WHOAMI_DB1100) {
510		c0 = AU1100_GPIO2_INT;
511		c1 = AU1100_GPIO5_INT;
512		d0 = AU1100_GPIO0_INT;
513		d1 = AU1100_GPIO3_INT;
514		s0 = AU1100_GPIO1_INT;
515		s1 = AU1100_GPIO4_INT;
516
517		gpio_request(19, "sd0_cd");
518		gpio_request(20, "sd1_cd");
519		gpio_direction_input(19);	/* sd0 cd# */
520		gpio_direction_input(20);	/* sd1 cd# */
521
522		/* spi_gpio on SSI0 pins */
523		pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
524		pfc |= (1 << 0);	/* SSI0 pins as GPIOs */
525		alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
526
527		spi_register_board_info(db1100_spi_info,
528					ARRAY_SIZE(db1100_spi_info));
529
530		/* link LCD clock to AUXPLL */
531		p = clk_get(NULL, "auxpll_clk");
532		c = clk_get(NULL, "lcd_intclk");
533		if (!IS_ERR(c) && !IS_ERR(p)) {
534			clk_set_parent(c, p);
535			clk_set_rate(c, clk_get_rate(p));
536		}
537		if (!IS_ERR(c))
538			clk_put(c);
539		if (!IS_ERR(p))
540			clk_put(p);
541
542		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
543		platform_device_register(&db1100_spi_dev);
544	} else if (board == BCSR_WHOAMI_DB1000) {
545		c0 = AU1000_GPIO2_INT;
546		c1 = AU1000_GPIO5_INT;
547		d0 = AU1000_GPIO0_INT;
548		d1 = AU1000_GPIO3_INT;
549		s0 = AU1000_GPIO1_INT;
550		s1 = AU1000_GPIO4_INT;
551		platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs));
552	} else if ((board == BCSR_WHOAMI_PB1500) ||
553		   (board == BCSR_WHOAMI_PB1500R2)) {
554		c0 = AU1500_GPIO203_INT;
555		d0 = AU1500_GPIO201_INT;
556		s0 = AU1500_GPIO202_INT;
557		twosocks = 0;
558		flashsize = 64;
559		/* RTC and daughtercard irqs */
560		irq_set_irq_type(AU1500_GPIO204_INT, IRQ_TYPE_LEVEL_LOW);
561		irq_set_irq_type(AU1500_GPIO205_INT, IRQ_TYPE_LEVEL_LOW);
562		/* EPSON S1D13806 0x1b000000
563		 * SRAM 1MB/2MB	  0x1a000000
564		 * DS1693 RTC	  0x0c000000
565		 */
566	} else if (board == BCSR_WHOAMI_PB1100) {
567		c0 = AU1100_GPIO11_INT;
568		d0 = AU1100_GPIO9_INT;
569		s0 = AU1100_GPIO10_INT;
570		twosocks = 0;
571		flashsize = 64;
572		/* pendown, rtc, daughtercard irqs */
573		irq_set_irq_type(AU1100_GPIO8_INT, IRQ_TYPE_LEVEL_LOW);
574		irq_set_irq_type(AU1100_GPIO12_INT, IRQ_TYPE_LEVEL_LOW);
575		irq_set_irq_type(AU1100_GPIO13_INT, IRQ_TYPE_LEVEL_LOW);
576		/* EPSON S1D13806 0x1b000000
577		 * SRAM 1MB/2MB	  0x1a000000
578		 * DiskOnChip	  0x0d000000
579		 * DS1693 RTC	  0x0c000000
580		 */
581		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
582	} else
583		return 0; /* unknown board, no further dev setup to do */
584
585	irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH);
586	irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
587	irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
588
589	db1x_register_pcmcia_socket(
590		AU1000_PCMCIA_ATTR_PHYS_ADDR,
591		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
592		AU1000_PCMCIA_MEM_PHYS_ADDR,
593		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
594		AU1000_PCMCIA_IO_PHYS_ADDR,
595		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
596		c0, d0, /*s0*/0, 0, 0);
597
598	if (twosocks) {
599		irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH);
600		irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
601		irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);
602
603		db1x_register_pcmcia_socket(
604			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
605			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
606			AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
607			AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
608			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
609			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
610			c1, d1, /*s1*/0, 0, 1);
611	}
612
613	platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs));
614	db1x_register_norflash(flashsize << 20, 4 /* 32bit */, F_SWAPPED);
615	return 0;
616}
617