[AVR32] Add support for ATSTK1003 and ATSTK1004

ATSTK1003 and ATSTK1004 are CPU daughterboards for ATSTK1000 featuring
the AT32AP7001 and AT32AP7002 CPUs, respectively.

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig
index 23e8c84..28c4780 100644
--- a/arch/avr32/boards/atstk1000/Kconfig
+++ b/arch/avr32/boards/atstk1000/Kconfig
@@ -1,34 +1,34 @@
 # STK1000 customization
 
-if BOARD_ATSTK1002
+if BOARD_ATSTK1000
 
-config BOARD_ATSTK1002_CUSTOM
-	bool "Non-default STK-1002 jumper settings"
+config BOARD_ATSTK100X_CUSTOM
+	bool "Non-default STK1002/STK1003/STK1004 jumper settings"
 	help
 	  You will normally leave the jumpers on the CPU card at their
 	  default settings.  If you need to use certain peripherals,
 	  you will need to change some of those jumpers.
 
-if BOARD_ATSTK1002_CUSTOM
+if BOARD_ATSTK100X_CUSTOM
 
-config BOARD_ATSTK1002_SW1_CUSTOM
+config BOARD_ATSTK100X_SW1_CUSTOM
 	bool "SW1: use SSC1 (not SPI0)"
 	help
 	  This also prevents using the external DAC as an audio interface,
 	  and means you can't initialize the on-board QVGA display.
 
-config BOARD_ATSTK1002_SW2_CUSTOM
+config BOARD_ATSTK100X_SW2_CUSTOM
 	bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)"
 	help
 	  If you change this you'll want an updated boot loader putting
 	  the console on UART-C not UART-A.
 
-config BOARD_ATSTK1002_SW3_CUSTOM
+config BOARD_ATSTK100X_SW3_CUSTOM
 	bool "SW3: use TIMER1 (not SSC0 and GCLK)"
 	help
 	  This also prevents using the external DAC as an audio interface.
 
-config BOARD_ATSTK1002_SW4_CUSTOM
+config BOARD_ATSTK100X_SW4_CUSTOM
 	bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)"
 	help
 	  To use the camera interface you'll need a custom card (on the
@@ -36,15 +36,17 @@
 
 config BOARD_ATSTK1002_SW5_CUSTOM
 	bool "SW5: use MACB1 (not LCDC)"
+	depends on BOARD_ATSTK1002
 
 config BOARD_ATSTK1002_SW6_CUSTOM
 	bool "SW6: more GPIOs (not MACB0)"
+	depends on BOARD_ATSTK1002
 
 endif	# custom
 
-config BOARD_ATSTK1002_SPI1
+config BOARD_ATSTK100X_SPI1
 	bool "Configure SPI1 controller"
-	depends on !BOARD_ATSTK1002_SW4_CUSTOM
+	depends on !BOARD_ATSTK100X_SW4_CUSTOM
 	help
 	  All the signals for the second SPI controller are available on
 	  GPIO lines and accessed through the J1 jumper block.  Say "y"
@@ -56,7 +58,7 @@
 
 choice
 	prompt "LEDs connected to J2:"
-	depends on LEDS_GPIO && !BOARD_ATSTK1002_SW4_CUSTOM
+	depends on LEDS_GPIO && !BOARD_ATSTK100X_SW4_CUSTOM
 	optional
 	help
 	  Select this if you have jumpered the J2 jumper block to the
@@ -78,7 +80,7 @@
 
 config BOARD_ATSTK1000_EXTDAC
 	bool
-	depends on !BOARD_ATSTK1002_SW1_CUSTOM && !BOARD_ATSTK1002_SW3_CUSTOM
+	depends on !BOARD_ATSTK100X_SW1_CUSTOM && !BOARD_ATSTK100X_SW3_CUSTOM
 	default y
 
-endif	# stk 1002
+endif	# stk 1000
diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile
index 8e09922..beead86 100644
--- a/arch/avr32/boards/atstk1000/Makefile
+++ b/arch/avr32/boards/atstk1000/Makefile
@@ -1,2 +1,4 @@
 obj-y				+= setup.o flash.o
 obj-$(CONFIG_BOARD_ATSTK1002)	+= atstk1002.o
+obj-$(CONFIG_BOARD_ATSTK1003)	+= atstk1003.o
+obj-$(CONFIG_BOARD_ATSTK1004)	+= atstk1004.o
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 57f610e..000eb42 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -55,7 +55,7 @@
 };
 #endif
 
-#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
+#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM
 static struct spi_board_info spi0_board_info[] __initdata = {
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 	{
@@ -77,7 +77,7 @@
 };
 #endif
 
-#ifdef CONFIG_BOARD_ATSTK1002_SPI1
+#ifdef CONFIG_BOARD_ATSTK100X_SPI1
 static struct spi_board_info spi1_board_info[] __initdata = { {
 	/* patch in custom entries here */
 } };
@@ -175,7 +175,7 @@
 
 void __init setup_board(void)
 {
-#ifdef	CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
+#ifdef	CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 	at32_map_usart(0, 1);	/* USART 0/B: /dev/ttyS1, IRDA */
 #else
 	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */
@@ -212,7 +212,7 @@
 
 	at32_add_system_devices();
 
-#ifdef	CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
+#ifdef	CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 	at32_add_device_usart(1);
 #else
 	at32_add_device_usart(0);
@@ -222,10 +222,10 @@
 #ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
 	set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
 #endif
-#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
+#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM
 	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
 #endif
-#ifdef CONFIG_BOARD_ATSTK1002_SPI1
+#ifdef CONFIG_BOARD_ATSTK100X_SPI1
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
@@ -235,7 +235,7 @@
 			     fbmem_start, fbmem_size);
 #endif
 	at32_add_device_usba(0, NULL);
-#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
+#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
 	at32_add_device_ssc(0, ATMEL_SSC_TX);
 #endif
 
diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c
new file mode 100644
index 0000000..a0b223d
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/atstk1003.c
@@ -0,0 +1,162 @@
+/*
+ * ATSTK1003 daughterboard-specific init code
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <linux/spi/at73c213.h>
+#include <linux/spi/spi.h>
+
+#include <asm/setup.h>
+
+#include <asm/arch/at32ap700x.h>
+#include <asm/arch/board.h>
+#include <asm/arch/init.h>
+#include <asm/arch/portmux.h>
+
+#include "atstk1000.h"
+
+#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
+static struct at73c213_board_info at73c213_data = {
+	.ssc_id		= 0,
+	.shortname	= "AVR32 STK1000 external DAC",
+};
+#endif
+
+#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM
+static struct spi_board_info spi0_board_info[] __initdata = {
+#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
+	{
+		/* AT73C213 */
+		.modalias	= "at73c213",
+		.max_speed_hz	= 200000,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_1,
+		.platform_data	= &at73c213_data,
+	},
+#endif
+	/*
+	 * We can control the LTV350QV LCD panel, but it isn't much
+	 * point since we don't have an LCD controller...
+	 */
+};
+#endif
+
+#ifdef CONFIG_BOARD_ATSTK100X_SPI1
+static struct spi_board_info spi1_board_info[] __initdata = { {
+	/* patch in custom entries here */
+} };
+#endif
+
+#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
+static void __init atstk1003_setup_extdac(void)
+{
+	struct clk *gclk;
+	struct clk *pll;
+
+	gclk = clk_get(NULL, "gclk0");
+	if (IS_ERR(gclk))
+		goto err_gclk;
+	pll = clk_get(NULL, "pll0");
+	if (IS_ERR(pll))
+		goto err_pll;
+
+	if (clk_set_parent(gclk, pll)) {
+		pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n");
+		goto err_set_clk;
+	}
+
+	at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
+	at73c213_data.dac_clk = gclk;
+
+err_set_clk:
+	clk_put(pll);
+err_pll:
+	clk_put(gclk);
+err_gclk:
+	return;
+}
+#else
+static void __init atstk1003_setup_extdac(void)
+{
+
+}
+#endif /* CONFIG_BOARD_ATSTK1000_EXTDAC */
+
+void __init setup_board(void)
+{
+#ifdef	CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+	at32_map_usart(0, 1);	/* USART 0/B: /dev/ttyS1, IRDA */
+#else
+	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */
+#endif
+	/* USART 2/unused: expansion connector */
+	at32_map_usart(3, 2);	/* USART 3/C: /dev/ttyS2, DB9 */
+
+	at32_setup_serial_console(0);
+}
+
+static int __init atstk1003_init(void)
+{
+	/*
+	 * ATSTK1000 uses 32-bit SDRAM interface. Reserve the
+	 * SDRAM-specific pins so that nobody messes with them.
+	 */
+	at32_reserve_pin(GPIO_PIN_PE(0));	/* DATA[16]	*/
+	at32_reserve_pin(GPIO_PIN_PE(1));	/* DATA[17]	*/
+	at32_reserve_pin(GPIO_PIN_PE(2));	/* DATA[18]	*/
+	at32_reserve_pin(GPIO_PIN_PE(3));	/* DATA[19]	*/
+	at32_reserve_pin(GPIO_PIN_PE(4));	/* DATA[20]	*/
+	at32_reserve_pin(GPIO_PIN_PE(5));	/* DATA[21]	*/
+	at32_reserve_pin(GPIO_PIN_PE(6));	/* DATA[22]	*/
+	at32_reserve_pin(GPIO_PIN_PE(7));	/* DATA[23]	*/
+	at32_reserve_pin(GPIO_PIN_PE(8));	/* DATA[24]	*/
+	at32_reserve_pin(GPIO_PIN_PE(9));	/* DATA[25]	*/
+	at32_reserve_pin(GPIO_PIN_PE(10));	/* DATA[26]	*/
+	at32_reserve_pin(GPIO_PIN_PE(11));	/* DATA[27]	*/
+	at32_reserve_pin(GPIO_PIN_PE(12));	/* DATA[28]	*/
+	at32_reserve_pin(GPIO_PIN_PE(13));	/* DATA[29]	*/
+	at32_reserve_pin(GPIO_PIN_PE(14));	/* DATA[30]	*/
+	at32_reserve_pin(GPIO_PIN_PE(15));	/* DATA[31]	*/
+	at32_reserve_pin(GPIO_PIN_PE(26));	/* SDCS		*/
+
+	at32_add_system_devices();
+
+#ifdef	CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+	at32_add_device_usart(1);
+#else
+	at32_add_device_usart(0);
+#endif
+	at32_add_device_usart(2);
+
+#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM
+	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
+#endif
+#ifdef CONFIG_BOARD_ATSTK100X_SPI1
+	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
+#endif
+#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+	at32_add_device_mci(0);
+#endif
+	at32_add_device_usba(0, NULL);
+#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
+	at32_add_device_ssc(0, ATMEL_SSC_TX);
+#endif
+
+	atstk1000_setup_j2_leds();
+	atstk1003_setup_extdac();
+
+	return 0;
+}
+postcore_initcall(atstk1003_init);
diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c
new file mode 100644
index 0000000..5a77030
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/atstk1004.c
@@ -0,0 +1,147 @@
+/*
+ * ATSTK1003 daughterboard-specific init code
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <linux/spi/at73c213.h>
+#include <linux/spi/spi.h>
+
+#include <video/atmel_lcdc.h>
+
+#include <asm/setup.h>
+
+#include <asm/arch/at32ap700x.h>
+#include <asm/arch/board.h>
+#include <asm/arch/init.h>
+#include <asm/arch/portmux.h>
+
+#include "atstk1000.h"
+
+#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
+static struct at73c213_board_info at73c213_data = {
+	.ssc_id		= 0,
+	.shortname	= "AVR32 STK1000 external DAC",
+};
+#endif
+
+#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM
+static struct spi_board_info spi0_board_info[] __initdata = {
+#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
+	{
+		/* AT73C213 */
+		.modalias	= "at73c213",
+		.max_speed_hz	= 200000,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_1,
+		.platform_data	= &at73c213_data,
+	},
+#endif
+	{
+		/* QVGA display */
+		.modalias	= "ltv350qv",
+		.max_speed_hz	= 16000000,
+		.chip_select	= 1,
+		.mode		= SPI_MODE_3,
+	},
+};
+#endif
+
+#ifdef CONFIG_BOARD_ATSTK100X_SPI1
+static struct spi_board_info spi1_board_info[] __initdata = { {
+	/* patch in custom entries here */
+} };
+#endif
+
+#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
+static void __init atstk1004_setup_extdac(void)
+{
+	struct clk *gclk;
+	struct clk *pll;
+
+	gclk = clk_get(NULL, "gclk0");
+	if (IS_ERR(gclk))
+		goto err_gclk;
+	pll = clk_get(NULL, "pll0");
+	if (IS_ERR(pll))
+		goto err_pll;
+
+	if (clk_set_parent(gclk, pll)) {
+		pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n");
+		goto err_set_clk;
+	}
+
+	at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
+	at73c213_data.dac_clk = gclk;
+
+err_set_clk:
+	clk_put(pll);
+err_pll:
+	clk_put(gclk);
+err_gclk:
+	return;
+}
+#else
+static void __init atstk1004_setup_extdac(void)
+{
+
+}
+#endif /* CONFIG_BOARD_ATSTK1000_EXTDAC */
+
+void __init setup_board(void)
+{
+#ifdef	CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+	at32_map_usart(0, 1);	/* USART 0/B: /dev/ttyS1, IRDA */
+#else
+	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */
+#endif
+	/* USART 2/unused: expansion connector */
+	at32_map_usart(3, 2);	/* USART 3/C: /dev/ttyS2, DB9 */
+
+	at32_setup_serial_console(0);
+}
+
+static int __init atstk1004_init(void)
+{
+	at32_add_system_devices();
+
+#ifdef	CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+	at32_add_device_usart(1);
+#else
+	at32_add_device_usart(0);
+#endif
+	at32_add_device_usart(2);
+
+#ifndef CONFIG_BOARD_ATSTK100X_SW1_CUSTOM
+	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
+#endif
+#ifdef CONFIG_BOARD_ATSTK100X_SPI1
+	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
+#endif
+#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
+	at32_add_device_mci(0);
+#endif
+	at32_add_device_lcdc(0, &atstk1000_lcdc_data,
+			     fbmem_start, fbmem_size);
+	at32_add_device_usba(0, NULL);
+#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
+	at32_add_device_ssc(0, ATMEL_SSC_TX);
+#endif
+
+	atstk1000_setup_j2_leds();
+	atstk1004_setup_extdac();
+
+	return 0;
+}
+postcore_initcall(atstk1004_init);