aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>2008-07-29 05:25:37 -0400
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-10-13 10:01:18 -0400
commit45c349b58c58f3922bfdec917aa30ff8425caa3f (patch)
tree1a120cdf16ebd97e0084e12a53a0ec6519d5c0a1
parenta3bee42f058c2f9fe281df942eff397924630a12 (diff)
avr32: add support for EarthLCD Favr-32 board
This patch adds support for the Favr-32 board made by EarthLCD. This kit, which is also called ezLCD-101, has a 10.4" touch screen LCD panel, 16 MB 32-bit SDRAM, 8 MB parallel flash, Ethernet, audio out, USB device, SD-card slot, USART and various other connectors for cennecting stuff to SPI, I2C, GPIO, etc. Signed-off-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
-rw-r--r--arch/avr32/Kconfig5
-rw-r--r--arch/avr32/Makefile1
-rw-r--r--arch/avr32/boards/favr-32/Kconfig22
-rw-r--r--arch/avr32/boards/favr-32/Makefile1
-rw-r--r--arch/avr32/boards/favr-32/flash.c98
-rw-r--r--arch/avr32/boards/favr-32/setup.c352
6 files changed, 479 insertions, 0 deletions
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 5c6d429505e1..856fcf3b2761 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -119,10 +119,15 @@ config BOARD_ATSTK1000
119config BOARD_ATNGW100 119config BOARD_ATNGW100
120 bool "ATNGW100 Network Gateway" 120 bool "ATNGW100 Network Gateway"
121 select CPU_AT32AP7000 121 select CPU_AT32AP7000
122
123config BOARD_FAVR_32
124 bool "Favr-32 LCD-board"
125 select CPU_AT32AP7000
122endchoice 126endchoice
123 127
124source "arch/avr32/boards/atstk1000/Kconfig" 128source "arch/avr32/boards/atstk1000/Kconfig"
125source "arch/avr32/boards/atngw100/Kconfig" 129source "arch/avr32/boards/atngw100/Kconfig"
130source "arch/avr32/boards/favr-32/Kconfig"
126 131
127choice 132choice
128 prompt "Boot loader type" 133 prompt "Boot loader type"
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
index c9e1f0b47fd3..9a0bfdbd7461 100644
--- a/arch/avr32/Makefile
+++ b/arch/avr32/Makefile
@@ -33,6 +33,7 @@ head-y += arch/avr32/kernel/head.o
33core-y += $(machdirs) 33core-y += $(machdirs)
34core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/ 34core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
35core-$(CONFIG_BOARD_ATNGW100) += arch/avr32/boards/atngw100/ 35core-$(CONFIG_BOARD_ATNGW100) += arch/avr32/boards/atngw100/
36core-$(CONFIG_BOARD_FAVR_32) += arch/avr32/boards/favr-32/
36core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/ 37core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
37core-y += arch/avr32/kernel/ 38core-y += arch/avr32/kernel/
38core-y += arch/avr32/mm/ 39core-y += arch/avr32/mm/
diff --git a/arch/avr32/boards/favr-32/Kconfig b/arch/avr32/boards/favr-32/Kconfig
new file mode 100644
index 000000000000..2c83d1ddcaec
--- /dev/null
+++ b/arch/avr32/boards/favr-32/Kconfig
@@ -0,0 +1,22 @@
1# Favr-32 customization
2
3if BOARD_FAVR_32
4
5config BOARD_FAVR32_ABDAC_RATE
6 int "DAC target rate"
7 default 44100
8 range 32000 50000
9 help
10 Specify the target rate the internal DAC should try to match. This
11 will use PLL1 to generate a frequency as close as possible to this
12 rate.
13
14 Must be within the range 32000 to 50000, which should be suitable to
15 generate most other frequencies in power of 2 steps.
16
17 Ex:
18 48000 will also suit 24000 and 12000
19 44100 will also suit 22050 and 11025
20 32000 will also suit 16000 and 8000
21
22endif # BOARD_FAVR_32
diff --git a/arch/avr32/boards/favr-32/Makefile b/arch/avr32/boards/favr-32/Makefile
new file mode 100644
index 000000000000..234f21508e4b
--- /dev/null
+++ b/arch/avr32/boards/favr-32/Makefile
@@ -0,0 +1 @@
obj-y += setup.o flash.o
diff --git a/arch/avr32/boards/favr-32/flash.c b/arch/avr32/boards/favr-32/flash.c
new file mode 100644
index 000000000000..5f139b7cb5f7
--- /dev/null
+++ b/arch/avr32/boards/favr-32/flash.c
@@ -0,0 +1,98 @@
1/*
2 * Favr-32 board-specific flash initialization
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/init.h>
11#include <linux/platform_device.h>
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/partitions.h>
14#include <linux/mtd/physmap.h>
15
16#include <asm/arch/smc.h>
17
18static struct smc_timing flash_timing __initdata = {
19 .ncs_read_setup = 0,
20 .nrd_setup = 40,
21 .ncs_write_setup = 0,
22 .nwe_setup = 10,
23
24 .ncs_read_pulse = 80,
25 .nrd_pulse = 40,
26 .ncs_write_pulse = 65,
27 .nwe_pulse = 55,
28
29 .read_cycle = 120,
30 .write_cycle = 120,
31};
32
33static struct smc_config flash_config __initdata = {
34 .bus_width = 2,
35 .nrd_controlled = 1,
36 .nwe_controlled = 1,
37 .byte_write = 1,
38};
39
40static struct mtd_partition flash_parts[] = {
41 {
42 .name = "u-boot",
43 .offset = 0x00000000,
44 .size = 0x00020000, /* 128 KiB */
45 .mask_flags = MTD_WRITEABLE,
46 },
47 {
48 .name = "root",
49 .offset = 0x00020000,
50 .size = 0x007d0000,
51 },
52 {
53 .name = "env",
54 .offset = 0x007f0000,
55 .size = 0x00010000,
56 .mask_flags = MTD_WRITEABLE,
57 },
58};
59
60static struct physmap_flash_data flash_data = {
61 .width = 2,
62 .nr_parts = ARRAY_SIZE(flash_parts),
63 .parts = flash_parts,
64};
65
66static struct resource flash_resource = {
67 .start = 0x00000000,
68 .end = 0x007fffff,
69 .flags = IORESOURCE_MEM,
70};
71
72static struct platform_device flash_device = {
73 .name = "physmap-flash",
74 .id = 0,
75 .resource = &flash_resource,
76 .num_resources = 1,
77 .dev = {
78 .platform_data = &flash_data,
79 },
80};
81
82/* This needs to be called after the SMC has been initialized */
83static int __init favr32_flash_init(void)
84{
85 int ret;
86
87 smc_set_timing(&flash_config, &flash_timing);
88 ret = smc_set_configuration(0, &flash_config);
89 if (ret < 0) {
90 printk(KERN_ERR "Favr-32: failed to set NOR flash timing\n");
91 return ret;
92 }
93
94 platform_device_register(&flash_device);
95
96 return 0;
97}
98device_initcall(favr32_flash_init);
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
new file mode 100644
index 000000000000..7538f3d2b9e0
--- /dev/null
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -0,0 +1,352 @@
1/*
2 * Favr-32 board-specific setup code.
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/clk.h>
11#include <linux/etherdevice.h>
12#include <linux/bootmem.h>
13#include <linux/fb.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/types.h>
17#include <linux/linkage.h>
18#include <linux/gpio.h>
19#include <linux/leds.h>
20#include <linux/atmel-pwm-bl.h>
21#include <linux/spi/spi.h>
22#include <linux/spi/ads7846.h>
23
24#include <video/atmel_lcdc.h>
25
26#include <asm/setup.h>
27
28#include <asm/arch/at32ap700x.h>
29#include <asm/arch/init.h>
30#include <asm/arch/board.h>
31#include <asm/arch/portmux.h>
32
33/* Oscillator frequencies. These are board-specific */
34unsigned long at32_board_osc_rates[3] = {
35 [0] = 32768, /* 32.768 kHz on RTC osc */
36 [1] = 20000000, /* 20 MHz on osc0 */
37 [2] = 12000000, /* 12 MHz on osc1 */
38};
39
40/* Initialized by bootloader-specific startup code. */
41struct tag *bootloader_tags __initdata;
42
43struct eth_addr {
44 u8 addr[6];
45};
46static struct eth_addr __initdata hw_addr[1];
47static struct eth_platform_data __initdata eth_data[1] = {
48 {
49 .phy_mask = ~(1U << 1),
50 },
51};
52
53static int ads7843_get_pendown_state(void)
54{
55 return !gpio_get_value(GPIO_PIN_PB(3));
56}
57
58static struct ads7846_platform_data ads7843_data = {
59 .model = 7843,
60 .get_pendown_state = ads7843_get_pendown_state,
61 .pressure_max = 255,
62 /*
63 * Values below are for debounce filtering, these can be experimented
64 * with further.
65 */
66 .debounce_max = 20,
67 .debounce_rep = 4,
68 .debounce_tol = 5,
69};
70
71static struct spi_board_info __initdata spi1_board_info[] = {
72 {
73 /* ADS7843 touch controller */
74 .modalias = "ads7846",
75 .max_speed_hz = 2000000,
76 .chip_select = 0,
77 .bus_num = 1,
78 .platform_data = &ads7843_data,
79 },
80};
81
82static struct fb_videomode __initdata lb104v03_modes[] = {
83 {
84 .name = "640x480 @ 50",
85 .refresh = 50,
86 .xres = 640, .yres = 480,
87 .pixclock = KHZ2PICOS(25100),
88
89 .left_margin = 90, .right_margin = 70,
90 .upper_margin = 30, .lower_margin = 15,
91 .hsync_len = 12, .vsync_len = 2,
92
93 .sync = 0,
94 .vmode = FB_VMODE_NONINTERLACED,
95 },
96};
97
98static struct fb_monspecs __initdata favr32_default_monspecs = {
99 .manufacturer = "LG",
100 .monitor = "LB104V03",
101 .modedb = lb104v03_modes,
102 .modedb_len = ARRAY_SIZE(lb104v03_modes),
103 .hfmin = 27273,
104 .hfmax = 31111,
105 .vfmin = 45,
106 .vfmax = 60,
107 .dclkmax = 28000000,
108};
109
110struct atmel_lcdfb_info __initdata favr32_lcdc_data = {
111 .default_bpp = 16,
112 .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
113 .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
114 | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
115 | ATMEL_LCDC_MEMOR_BIG),
116 .default_monspecs = &favr32_default_monspecs,
117 .guard_time = 2,
118};
119
120static struct gpio_led favr32_leds[] = {
121 {
122 .name = "green",
123 .gpio = GPIO_PIN_PE(19),
124 .default_trigger = "heartbeat",
125 .active_low = 1,
126 },
127 {
128 .name = "red",
129 .gpio = GPIO_PIN_PE(20),
130 .active_low = 1,
131 },
132};
133
134static struct gpio_led_platform_data favr32_led_data = {
135 .num_leds = ARRAY_SIZE(favr32_leds),
136 .leds = favr32_leds,
137};
138
139static struct platform_device favr32_led_dev = {
140 .name = "leds-gpio",
141 .id = 0,
142 .dev = {
143 .platform_data = &favr32_led_data,
144 },
145};
146
147/*
148 * The next two functions should go away as the boot loader is
149 * supposed to initialize the macb address registers with a valid
150 * ethernet address. But we need to keep it around for a while until
151 * we can be reasonably sure the boot loader does this.
152 *
153 * The phy_id is ignored as the driver will probe for it.
154 */
155static int __init parse_tag_ethernet(struct tag *tag)
156{
157 int i;
158
159 i = tag->u.ethernet.mac_index;
160 if (i < ARRAY_SIZE(hw_addr))
161 memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
162 sizeof(hw_addr[i].addr));
163
164 return 0;
165}
166__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
167
168static void __init set_hw_addr(struct platform_device *pdev)
169{
170 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
171 const u8 *addr;
172 void __iomem *regs;
173 struct clk *pclk;
174
175 if (!res)
176 return;
177 if (pdev->id >= ARRAY_SIZE(hw_addr))
178 return;
179
180 addr = hw_addr[pdev->id].addr;
181 if (!is_valid_ether_addr(addr))
182 return;
183
184 /*
185 * Since this is board-specific code, we'll cheat and use the
186 * physical address directly as we happen to know that it's
187 * the same as the virtual address.
188 */
189 regs = (void __iomem __force *)res->start;
190 pclk = clk_get(&pdev->dev, "pclk");
191 if (!pclk)
192 return;
193
194 clk_enable(pclk);
195 __raw_writel((addr[3] << 24) | (addr[2] << 16)
196 | (addr[1] << 8) | addr[0], regs + 0x98);
197 __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
198 clk_disable(pclk);
199 clk_put(pclk);
200}
201
202void __init favr32_setup_leds(void)
203{
204 unsigned i;
205
206 for (i = 0; i < ARRAY_SIZE(favr32_leds); i++)
207 at32_select_gpio(favr32_leds[i].gpio, AT32_GPIOF_OUTPUT);
208
209 platform_device_register(&favr32_led_dev);
210}
211
212static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = {
213 .pwm_channel = 2,
214 .pwm_frequency = 200000,
215 .pwm_compare_max = 345,
216 .pwm_duty_max = 345,
217 .pwm_duty_min = 90,
218 .pwm_active_low = 1,
219 .gpio_on = GPIO_PIN_PA(28),
220 .on_active_low = 0,
221};
222
223static struct platform_device atmel_pwm_bl_dev = {
224 .name = "atmel-pwm-bl",
225 .id = 0,
226 .dev = {
227 .platform_data = &atmel_pwm_bl_pdata,
228 },
229};
230
231static void __init favr32_setup_atmel_pwm_bl(void)
232{
233 platform_device_register(&atmel_pwm_bl_dev);
234 at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0);
235}
236
237void __init setup_board(void)
238{
239 at32_map_usart(3, 0); /* USART 3 => /dev/ttyS0 */
240 at32_setup_serial_console(0);
241}
242
243static int __init set_abdac_rate(struct platform_device *pdev)
244{
245 int retval;
246 struct clk *osc1;
247 struct clk *pll1;
248 struct clk *abdac;
249
250 if (pdev == NULL)
251 return -ENXIO;
252
253 osc1 = clk_get(NULL, "osc1");
254 if (IS_ERR(osc1)) {
255 retval = PTR_ERR(osc1);
256 goto out;
257 }
258
259 pll1 = clk_get(NULL, "pll1");
260 if (IS_ERR(pll1)) {
261 retval = PTR_ERR(pll1);
262 goto out_osc1;
263 }
264
265 abdac = clk_get(&pdev->dev, "sample_clk");
266 if (IS_ERR(abdac)) {
267 retval = PTR_ERR(abdac);
268 goto out_pll1;
269 }
270
271 retval = clk_set_parent(pll1, osc1);
272 if (retval != 0)
273 goto out_abdac;
274
275 /*
276 * Rate is 32000 to 50000 and ABDAC oversamples 256x. Multiply, in
277 * power of 2, to a value above 80 MHz. Power of 2 so it is possible
278 * for the generic clock to divide it down again and 80 MHz is the
279 * lowest frequency for the PLL.
280 */
281 retval = clk_round_rate(pll1,
282 CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16);
283 if (retval < 0)
284 goto out_abdac;
285
286 retval = clk_set_rate(pll1, retval);
287 if (retval != 0)
288 goto out_abdac;
289
290 retval = clk_set_parent(abdac, pll1);
291 if (retval != 0)
292 goto out_abdac;
293
294out_abdac:
295 clk_put(abdac);
296out_pll1:
297 clk_put(pll1);
298out_osc1:
299 clk_put(osc1);
300out:
301 return retval;
302}
303
304static int __init favr32_init(void)
305{
306 /*
307 * Favr-32 uses 32-bit SDRAM interface. Reserve the SDRAM-specific
308 * pins so that nobody messes with them.
309 */
310 at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
311 at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
312 at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
313 at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
314 at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
315 at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
316 at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
317 at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
318 at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
319 at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
320 at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
321 at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
322 at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
323 at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
324 at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
325 at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
326 at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
327
328 at32_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */
329
330 at32_add_system_devices();
331
332 at32_add_device_usart(0);
333
334 set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
335
336 spi1_board_info[0].irq = gpio_to_irq(GPIO_PIN_PB(3));
337
338 set_abdac_rate(at32_add_device_abdac(0));
339
340 at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel);
341 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
342 at32_add_device_mci(0, NULL);
343 at32_add_device_usba(0, NULL);
344 at32_add_device_lcdc(0, &favr32_lcdc_data, fbmem_start, fbmem_size, 0);
345
346 favr32_setup_leds();
347
348 favr32_setup_atmel_pwm_bl();
349
350 return 0;
351}
352postcore_initcall(favr32_init);