diff options
Diffstat (limited to 'arch/avr32/boards')
-rw-r--r-- | arch/avr32/boards/atngw100/Kconfig | 35 | ||||
-rw-r--r-- | arch/avr32/boards/atngw100/Makefile | 3 | ||||
-rw-r--r-- | arch/avr32/boards/atngw100/evklcd10x.c | 155 | ||||
-rw-r--r-- | arch/avr32/boards/atngw100/setup.c | 5 | ||||
-rw-r--r-- | arch/avr32/boards/favr-32/Kconfig | 22 | ||||
-rw-r--r-- | arch/avr32/boards/favr-32/Makefile | 1 | ||||
-rw-r--r-- | arch/avr32/boards/favr-32/flash.c | 98 | ||||
-rw-r--r-- | arch/avr32/boards/favr-32/setup.c | 352 | ||||
-rw-r--r-- | arch/avr32/boards/mimc200/Makefile | 1 | ||||
-rw-r--r-- | arch/avr32/boards/mimc200/flash.c | 143 | ||||
-rw-r--r-- | arch/avr32/boards/mimc200/fram.c | 80 | ||||
-rw-r--r-- | arch/avr32/boards/mimc200/setup.c | 237 |
12 files changed, 1131 insertions, 1 deletions
diff --git a/arch/avr32/boards/atngw100/Kconfig b/arch/avr32/boards/atngw100/Kconfig new file mode 100644 index 00000000000..b3f99477bbe --- /dev/null +++ b/arch/avr32/boards/atngw100/Kconfig @@ -0,0 +1,35 @@ +# NGW100 customization + +if BOARD_ATNGW100 + +config BOARD_ATNGW100_EVKLCD10X + bool "Add support for EVKLCD10X addon board" + help + This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA) + addon board for the NGW100. By enabling this the LCD controller and + AC97 controller is added as platform devices. + + This choice disables the detect pin and the write-protect pin for the + MCI platform device, since it conflicts with the LCD platform device. + The MCI pins can be reenabled by editing the "add device function" but + this may break the setup for other displays that use these pins. + + Choose 'Y' here if you have a EVKLCD100/101 connected to the NGW100. + +choice + prompt "LCD panel resolution on EVKLCD10X" + depends on BOARD_ATNGW100_EVKLCD10X + default BOARD_ATNGW100_EVKLCD10X_VGA + +config BOARD_ATNGW100_EVKLCD10X_QVGA + bool "QVGA (320x240)" + +config BOARD_ATNGW100_EVKLCD10X_VGA + bool "VGA (640x480)" + +config BOARD_ATNGW100_EVKLCD10X_POW_QVGA + bool "Powertip QVGA (320x240)" + +endchoice + +endif # BOARD_ATNGW100 diff --git a/arch/avr32/boards/atngw100/Makefile b/arch/avr32/boards/atngw100/Makefile index c740aa11675..6376f5322e4 100644 --- a/arch/avr32/boards/atngw100/Makefile +++ b/arch/avr32/boards/atngw100/Makefile @@ -1 +1,2 @@ -obj-y += setup.o flash.o +obj-y += setup.o flash.o +obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X) += evklcd10x.o diff --git a/arch/avr32/boards/atngw100/evklcd10x.c b/arch/avr32/boards/atngw100/evklcd10x.c new file mode 100644 index 00000000000..8140b22b346 --- /dev/null +++ b/arch/avr32/boards/atngw100/evklcd10x.c @@ -0,0 +1,155 @@ +/* + * Board-specific setup code for the ATEVKLCD10X addon board to the ATNGW100 + * Network Gateway + * + * Copyright (C) 2008 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/init.h> +#include <linux/linkage.h> +#include <linux/fb.h> +#include <linux/platform_device.h> + +#include <video/atmel_lcdc.h> + +#include <asm/setup.h> + +#include <mach/at32ap700x.h> +#include <mach/board.h> + +static struct ac97c_platform_data __initdata ac97c0_data = { + .dma_rx_periph_id = 3, + .dma_tx_periph_id = 4, + .dma_controller_id = 0, + .reset_pin = GPIO_PIN_PB(19), +}; + +#ifdef CONFIG_BOARD_ATNGW100_EVKLCD10X_VGA +static struct fb_videomode __initdata tcg057vglad_modes[] = { + { + .name = "640x480 @ 60", + .refresh = 60, + .xres = 640, .yres = 480, + .pixclock = KHZ2PICOS(25180), + + .left_margin = 64, .right_margin = 31, + .upper_margin = 34, .lower_margin = 2, + .hsync_len = 96, .vsync_len = 4, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { + .manufacturer = "KYO", + .monitor = "TCG057VGLAD", + .modedb = tcg057vglad_modes, + .modedb_len = ARRAY_SIZE(tcg057vglad_modes), + .hfmin = 19948, + .hfmax = 31478, + .vfmin = 50, + .vfmax = 67, + .dclkmax = 28330000, +}; + +static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = { + .default_bpp = 16, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &atevklcd10x_default_monspecs, + .guard_time = 2, +}; +#elif CONFIG_BOARD_ATNGW100_EVKLCD10X_QVGA +static struct fb_videomode __initdata tcg057qvlad_modes[] = { + { + .name = "320x240 @ 60", + .refresh = 60, + .xres = 320, .yres = 240, + .pixclock = KHZ2PICOS(6300), + + .left_margin = 52, .right_margin = 28, + .upper_margin = 7, .lower_margin = 2, + .hsync_len = 96, .vsync_len = 4, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { + .manufacturer = "KYO", + .monitor = "TCG057QVLAD", + .modedb = tcg057qvlad_modes, + .modedb_len = ARRAY_SIZE(tcg057qvlad_modes), + .hfmin = 19948, + .hfmax = 31478, + .vfmin = 50, + .vfmax = 67, + .dclkmax = 7000000, +}; + +static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = { + .default_bpp = 16, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &atevklcd10x_default_monspecs, + .guard_time = 2, +}; +#elif CONFIG_BOARD_ATNGW100_EVKLCD10X_POW_QVGA +static struct fb_videomode __initdata ph320240t_modes[] = { + { + .name = "320x240 @ 60", + .refresh = 60, + .xres = 320, .yres = 240, + .pixclock = KHZ2PICOS(6300), + + .left_margin = 38, .right_margin = 20, + .upper_margin = 15, .lower_margin = 5, + .hsync_len = 30, .vsync_len = 3, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata atevklcd10x_default_monspecs = { + .manufacturer = "POW", + .monitor = "PH320240T", + .modedb = ph320240t_modes, + .modedb_len = ARRAY_SIZE(ph320240t_modes), + .hfmin = 14400, + .hfmax = 21600, + .vfmin = 50, + .vfmax = 90, + .dclkmax = 6400000, +}; + +static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = { + .default_bpp = 16, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &atevklcd10x_default_monspecs, + .guard_time = 2, +}; +#endif + +static int __init atevklcd10x_init(void) +{ + at32_add_device_ac97c(0, &ac97c0_data); + + at32_add_device_lcdc(0, &atevklcd10x_lcdc_data, + fbmem_start, fbmem_size, 1); + return 0; +} +postcore_initcall(atevklcd10x_init); diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 259ceee02b6..32fb9ba0fbd 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -56,8 +56,13 @@ static struct spi_board_info spi0_board_info[] __initdata = { static struct mci_platform_data __initdata mci0_data = { .slot[0] = { .bus_width = 4, +#ifndef CONFIG_BOARD_ATNGW100_EVKLCD10X .detect_pin = GPIO_PIN_PC(25), .wp_pin = GPIO_PIN_PE(0), +#else + .detect_pin = GPIO_PIN_NONE, + .wp_pin = GPIO_PIN_NONE, +#endif }, }; diff --git a/arch/avr32/boards/favr-32/Kconfig b/arch/avr32/boards/favr-32/Kconfig new file mode 100644 index 00000000000..2c83d1ddcae --- /dev/null +++ b/arch/avr32/boards/favr-32/Kconfig @@ -0,0 +1,22 @@ +# Favr-32 customization + +if BOARD_FAVR_32 + +config BOARD_FAVR32_ABDAC_RATE + int "DAC target rate" + default 44100 + range 32000 50000 + help + Specify the target rate the internal DAC should try to match. This + will use PLL1 to generate a frequency as close as possible to this + rate. + + Must be within the range 32000 to 50000, which should be suitable to + generate most other frequencies in power of 2 steps. + + Ex: + 48000 will also suit 24000 and 12000 + 44100 will also suit 22050 and 11025 + 32000 will also suit 16000 and 8000 + +endif # BOARD_FAVR_32 diff --git a/arch/avr32/boards/favr-32/Makefile b/arch/avr32/boards/favr-32/Makefile new file mode 100644 index 00000000000..234f21508e4 --- /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 00000000000..5f139b7cb5f --- /dev/null +++ b/arch/avr32/boards/favr-32/flash.c @@ -0,0 +1,98 @@ +/* + * Favr-32 board-specific flash initialization + * + * Copyright (C) 2008 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/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> + +#include <asm/arch/smc.h> + +static struct smc_timing flash_timing __initdata = { + .ncs_read_setup = 0, + .nrd_setup = 40, + .ncs_write_setup = 0, + .nwe_setup = 10, + + .ncs_read_pulse = 80, + .nrd_pulse = 40, + .ncs_write_pulse = 65, + .nwe_pulse = 55, + + .read_cycle = 120, + .write_cycle = 120, +}; + +static struct smc_config flash_config __initdata = { + .bus_width = 2, + .nrd_controlled = 1, + .nwe_controlled = 1, + .byte_write = 1, +}; + +static struct mtd_partition flash_parts[] = { + { + .name = "u-boot", + .offset = 0x00000000, + .size = 0x00020000, /* 128 KiB */ + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "root", + .offset = 0x00020000, + .size = 0x007d0000, + }, + { + .name = "env", + .offset = 0x007f0000, + .size = 0x00010000, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data flash_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(flash_parts), + .parts = flash_parts, +}; + +static struct resource flash_resource = { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device = { + .name = "physmap-flash", + .id = 0, + .resource = &flash_resource, + .num_resources = 1, + .dev = { + .platform_data = &flash_data, + }, +}; + +/* This needs to be called after the SMC has been initialized */ +static int __init favr32_flash_init(void) +{ + int ret; + + smc_set_timing(&flash_config, &flash_timing); + ret = smc_set_configuration(0, &flash_config); + if (ret < 0) { + printk(KERN_ERR "Favr-32: failed to set NOR flash timing\n"); + return ret; + } + + platform_device_register(&flash_device); + + return 0; +} +device_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 00000000000..7538f3d2b9e --- /dev/null +++ b/arch/avr32/boards/favr-32/setup.c @@ -0,0 +1,352 @@ +/* + * Favr-32 board-specific setup code. + * + * Copyright (C) 2008 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/etherdevice.h> +#include <linux/bootmem.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/linkage.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <linux/atmel-pwm-bl.h> +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> + +#include <video/atmel_lcdc.h> + +#include <asm/setup.h> + +#include <asm/arch/at32ap700x.h> +#include <asm/arch/init.h> +#include <asm/arch/board.h> +#include <asm/arch/portmux.h> + +/* Oscillator frequencies. These are board-specific */ +unsigned long at32_board_osc_rates[3] = { + [0] = 32768, /* 32.768 kHz on RTC osc */ + [1] = 20000000, /* 20 MHz on osc0 */ + [2] = 12000000, /* 12 MHz on osc1 */ +}; + +/* Initialized by bootloader-specific startup code. */ +struct tag *bootloader_tags __initdata; + +struct eth_addr { + u8 addr[6]; +}; +static struct eth_addr __initdata hw_addr[1]; +static struct eth_platform_data __initdata eth_data[1] = { + { + .phy_mask = ~(1U << 1), + }, +}; + +static int ads7843_get_pendown_state(void) +{ + return !gpio_get_value(GPIO_PIN_PB(3)); +} + +static struct ads7846_platform_data ads7843_data = { + .model = 7843, + .get_pendown_state = ads7843_get_pendown_state, + .pressure_max = 255, + /* + * Values below are for debounce filtering, these can be experimented + * with further. + */ + .debounce_max = 20, + .debounce_rep = 4, + .debounce_tol = 5, +}; + +static struct spi_board_info __initdata spi1_board_info[] = { + { + /* ADS7843 touch controller */ + .modalias = "ads7846", + .max_speed_hz = 2000000, + .chip_select = 0, + .bus_num = 1, + .platform_data = &ads7843_data, + }, +}; + +static struct fb_videomode __initdata lb104v03_modes[] = { + { + .name = "640x480 @ 50", + .refresh = 50, + .xres = 640, .yres = 480, + .pixclock = KHZ2PICOS(25100), + + .left_margin = 90, .right_margin = 70, + .upper_margin = 30, .lower_margin = 15, + .hsync_len = 12, .vsync_len = 2, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata favr32_default_monspecs = { + .manufacturer = "LG", + .monitor = "LB104V03", + .modedb = lb104v03_modes, + .modedb_len = ARRAY_SIZE(lb104v03_modes), + .hfmin = 27273, + .hfmax = 31111, + .vfmin = 45, + .vfmax = 60, + .dclkmax = 28000000, +}; + +struct atmel_lcdfb_info __initdata favr32_lcdc_data = { + .default_bpp = 16, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &favr32_default_monspecs, + .guard_time = 2, +}; + +static struct gpio_led favr32_leds[] = { + { + .name = "green", + .gpio = GPIO_PIN_PE(19), + .default_trigger = "heartbeat", + .active_low = 1, + }, + { + .name = "red", + .gpio = GPIO_PIN_PE(20), + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data favr32_led_data = { + .num_leds = ARRAY_SIZE(favr32_leds), + .leds = favr32_leds, +}; + +static struct platform_device favr32_led_dev = { + .name = "leds-gpio", + .id = 0, + .dev = { + .platform_data = &favr32_led_data, + }, +}; + +/* + * The next two functions should go away as the boot loader is + * supposed to initialize the macb address registers with a valid + * ethernet address. But we need to keep it around for a while until + * we can be reasonably sure the boot loader does this. + * + * The phy_id is ignored as the driver will probe for it. + */ +static int __init parse_tag_ethernet(struct tag *tag) +{ + int i; + + i = tag->u.ethernet.mac_index; + if (i < ARRAY_SIZE(hw_addr)) + memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, + sizeof(hw_addr[i].addr)); + + return 0; +} +__tagtable(ATAG_ETHERNET, parse_tag_ethernet); + +static void __init set_hw_addr(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const u8 *addr; + void __iomem *regs; + struct clk *pclk; + + if (!res) + return; + if (pdev->id >= ARRAY_SIZE(hw_addr)) + return; + + addr = hw_addr[pdev->id].addr; + if (!is_valid_ether_addr(addr)) + return; + + /* + * Since this is board-specific code, we'll cheat and use the + * physical address directly as we happen to know that it's + * the same as the virtual address. + */ + regs = (void __iomem __force *)res->start; + pclk = clk_get(&pdev->dev, "pclk"); + if (!pclk) + return; + + clk_enable(pclk); + __raw_writel((addr[3] << 24) | (addr[2] << 16) + | (addr[1] << 8) | addr[0], regs + 0x98); + __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); + clk_disable(pclk); + clk_put(pclk); +} + +void __init favr32_setup_leds(void) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(favr32_leds); i++) + at32_select_gpio(favr32_leds[i].gpio, AT32_GPIOF_OUTPUT); + + platform_device_register(&favr32_led_dev); +} + +static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = { + .pwm_channel = 2, + .pwm_frequency = 200000, + .pwm_compare_max = 345, + .pwm_duty_max = 345, + .pwm_duty_min = 90, + .pwm_active_low = 1, + .gpio_on = GPIO_PIN_PA(28), + .on_active_low = 0, +}; + +static struct platform_device atmel_pwm_bl_dev = { + .name = "atmel-pwm-bl", + .id = 0, + .dev = { + .platform_data = &atmel_pwm_bl_pdata, + }, +}; + +static void __init favr32_setup_atmel_pwm_bl(void) +{ + platform_device_register(&atmel_pwm_bl_dev); + at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0); +} + +void __init setup_board(void) +{ + at32_map_usart(3, 0); /* USART 3 => /dev/ttyS0 */ + at32_setup_serial_console(0); +} + +static int __init set_abdac_rate(struct platform_device *pdev) +{ + int retval; + struct clk *osc1; + struct clk *pll1; + struct clk *abdac; + + if (pdev == NULL) + return -ENXIO; + + osc1 = clk_get(NULL, "osc1"); + if (IS_ERR(osc1)) { + retval = PTR_ERR(osc1); + goto out; + } + + pll1 = clk_get(NULL, "pll1"); + if (IS_ERR(pll1)) { + retval = PTR_ERR(pll1); + goto out_osc1; + } + + abdac = clk_get(&pdev->dev, "sample_clk"); + if (IS_ERR(abdac)) { + retval = PTR_ERR(abdac); + goto out_pll1; + } + + retval = clk_set_parent(pll1, osc1); + if (retval != 0) + goto out_abdac; + + /* + * Rate is 32000 to 50000 and ABDAC oversamples 256x. Multiply, in + * power of 2, to a value above 80 MHz. Power of 2 so it is possible + * for the generic clock to divide it down again and 80 MHz is the + * lowest frequency for the PLL. + */ + retval = clk_round_rate(pll1, + CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16); + if (retval < 0) + goto out_abdac; + + retval = clk_set_rate(pll1, retval); + if (retval != 0) + goto out_abdac; + + retval = clk_set_parent(abdac, pll1); + if (retval != 0) + goto out_abdac; + +out_abdac: + clk_put(abdac); +out_pll1: + clk_put(pll1); +out_osc1: + clk_put(osc1); +out: + return retval; +} + +static int __init favr32_init(void) +{ + /* + * Favr-32 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_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */ + + at32_add_system_devices(); + + at32_add_device_usart(0); + + set_hw_addr(at32_add_device_eth(0, ð_data[0])); + + spi1_board_info[0].irq = gpio_to_irq(GPIO_PIN_PB(3)); + + set_abdac_rate(at32_add_device_abdac(0)); + + at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel); + at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); + at32_add_device_mci(0, NULL); + at32_add_device_usba(0, NULL); + at32_add_device_lcdc(0, &favr32_lcdc_data, fbmem_start, fbmem_size, 0); + + favr32_setup_leds(); + + favr32_setup_atmel_pwm_bl(); + + return 0; +} +postcore_initcall(favr32_init); diff --git a/arch/avr32/boards/mimc200/Makefile b/arch/avr32/boards/mimc200/Makefile new file mode 100644 index 00000000000..79c076e168a --- /dev/null +++ b/arch/avr32/boards/mimc200/Makefile @@ -0,0 +1 @@ +obj-y += setup.o flash.o fram.o diff --git a/arch/avr32/boards/mimc200/flash.c b/arch/avr32/boards/mimc200/flash.c new file mode 100644 index 00000000000..d83d650fc13 --- /dev/null +++ b/arch/avr32/boards/mimc200/flash.c @@ -0,0 +1,143 @@ +/* + * MIMC200 board-specific flash initialization + * + * Copyright (C) 2008 Mercury IMC Ltd + * + * 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/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> + +#include <mach/smc.h> + +static struct smc_timing flash_timing __initdata = { + .ncs_read_setup = 0, + .nrd_setup = 15, + .ncs_write_setup = 0, + .nwe_setup = 0, + + .ncs_read_pulse = 115, + .nrd_pulse = 110, + .ncs_write_pulse = 60, + .nwe_pulse = 60, + + .read_cycle = 115, + .write_cycle = 100, +}; + +static struct smc_config flash_config __initdata = { + .bus_width = 2, + .nrd_controlled = 1, + .nwe_controlled = 1, + .byte_write = 1, +}; + +/* system flash definition */ + +static struct mtd_partition flash_parts_system[] = { + { + .name = "u-boot", + .offset = 0x00000000, + .size = 0x00020000, /* 128 KiB */ + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "root", + .offset = 0x00020000, + .size = 0x007c0000, + }, + { + .name = "splash", + .offset = 0x007e0000, + .size = 0x00010000, /* 64KiB */ + }, + { + .name = "env", + .offset = 0x007f0000, + .size = 0x00010000, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data flash_system = { + .width = 2, + .nr_parts = ARRAY_SIZE(flash_parts_system), + .parts = flash_parts_system, +}; + +static struct resource flash_resource_system = { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device_system = { + .name = "physmap-flash", + .id = 0, + .resource = &flash_resource_system, + .num_resources = 1, + .dev = { + .platform_data = &flash_system, + }, +}; + +/* data flash definition */ + +static struct mtd_partition flash_parts_data[] = { + { + .name = "data", + .offset = 0x00000000, + .size = 0x00800000, + }, +}; + +static struct physmap_flash_data flash_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(flash_parts_data), + .parts = flash_parts_data, +}; + +static struct resource flash_resource_data = { + .start = 0x08000000, + .end = 0x087fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device_data = { + .name = "physmap-flash", + .id = 1, + .resource = &flash_resource_data, + .num_resources = 1, + .dev = { + .platform_data = &flash_data, + }, +}; + +/* This needs to be called after the SMC has been initialized */ +static int __init mimc200_flash_init(void) +{ + int ret; + + smc_set_timing(&flash_config, &flash_timing); + ret = smc_set_configuration(0, &flash_config); + if (ret < 0) { + printk(KERN_ERR "mimc200: failed to set 'System' NOR flash timing\n"); + return ret; + } + ret = smc_set_configuration(1, &flash_config); + if (ret < 0) { + printk(KERN_ERR "mimc200: failed to set 'Data' NOR flash timing\n"); + return ret; + } + + platform_device_register(&flash_device_system); + platform_device_register(&flash_device_data); + + return 0; +} +device_initcall(mimc200_flash_init); diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c new file mode 100644 index 00000000000..54fbd95cee9 --- /dev/null +++ b/arch/avr32/boards/mimc200/fram.c @@ -0,0 +1,80 @@ +/* + * FRAM driver for MIMC200 board + * + * Copyright 2008 Mark Jackson <mpfj@mimc.co.uk> + * + * This module adds *very* simply support for the system's FRAM device. + * At the moment, this is hard-coded to the MIMC200 platform, and only + * supports mmap(). + */ + +#define FRAM_VERSION "1.0" + +#include <linux/miscdevice.h> +#include <linux/proc_fs.h> +#include <linux/mm.h> +#include <linux/io.h> + +#define FRAM_BASE 0xac000000 +#define FRAM_SIZE 0x20000 + +/* + * The are the file operation function for user access to /dev/fram + */ + +static int fram_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + + ret = remap_pfn_range(vma, + vma->vm_start, + virt_to_phys((void *)((unsigned long)FRAM_BASE)) >> PAGE_SHIFT, + vma->vm_end-vma->vm_start, + PAGE_SHARED); + + if (ret != 0) + return -EAGAIN; + + return 0; +} + +static const struct file_operations fram_fops = { + .owner = THIS_MODULE, + .mmap = fram_mmap, +}; + +#define FRAM_MINOR 0 + +static struct miscdevice fram_dev = { + FRAM_MINOR, + "fram", + &fram_fops +}; + +static int __init +fram_init(void) +{ + int ret; + + ret = misc_register(&fram_dev); + if (ret) { + printk(KERN_ERR "fram: can't misc_register on minor=%d\n", + FRAM_MINOR); + return ret; + } + printk(KERN_INFO "FRAM memory driver v" FRAM_VERSION "\n"); + return 0; +} + +static void __exit +fram_cleanup_module(void) +{ + misc_deregister(&fram_dev); +} + +module_init(fram_init); +module_exit(fram_cleanup_module); + +MODULE_LICENSE("GPL"); + +MODULE_ALIAS_MISCDEV(FRAM_MINOR); diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c new file mode 100644 index 00000000000..397cbb8f44c --- /dev/null +++ b/arch/avr32/boards/mimc200/setup.c @@ -0,0 +1,237 @@ +/* + * Board-specific setup code for the MIMC200 + * + * Copyright (C) 2008 Mercury IMC Ltd + * + * 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. + */ + +extern struct atmel_lcdfb_info mimc200_lcdc_data; + +#include <linux/clk.h> +#include <linux/etherdevice.h> +#include <linux/i2c-gpio.h> +#include <linux/init.h> +#include <linux/linkage.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/leds.h> +#include <linux/spi/spi.h> +#include <linux/spi/eeprom.h> + +#include <video/atmel_lcdc.h> +#include <linux/fb.h> + +#include <asm/atmel-mci.h> +#include <linux/io.h> +#include <asm/setup.h> + +#include <mach/at32ap700x.h> +#include <mach/board.h> +#include <mach/init.h> +#include <mach/portmux.h> + +/* Oscillator frequencies. These are board-specific */ +unsigned long at32_board_osc_rates[3] = { + [0] = 32768, /* 32.768 kHz on RTC osc */ + [1] = 10000000, /* 10 MHz on osc0 */ + [2] = 12000000, /* 12 MHz on osc1 */ +}; + +/* Initialized by bootloader-specific startup code. */ +struct tag *bootloader_tags __initdata; + +static struct fb_videomode __initdata tx14d14_modes[] = { + { + .name = "640x480 @ 60", + .refresh = 60, + .xres = 640, .yres = 480, + .pixclock = KHZ2PICOS(11666), + + .left_margin = 80, .right_margin = 1, + .upper_margin = 13, .lower_margin = 2, + .hsync_len = 64, .vsync_len = 1, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata mimc200_default_monspecs = { + .manufacturer = "HIT", + .monitor = "TX14D14VM1BAB", + .modedb = tx14d14_modes, + .modedb_len = ARRAY_SIZE(tx14d14_modes), + .hfmin = 14820, + .hfmax = 22230, + .vfmin = 60, + .vfmax = 73.3, + .dclkmax = 25200000, +}; + +struct atmel_lcdfb_info __initdata mimc200_lcdc_data = { + .default_bpp = 16, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_INVCLK + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &mimc200_default_monspecs, + .guard_time = 2, +}; + +struct eth_addr { + u8 addr[6]; +}; +static struct eth_addr __initdata hw_addr[2]; +static struct eth_platform_data __initdata eth_data[2]; + +static struct spi_eeprom eeprom_25lc010 = { + .name = "25lc010", + .byte_len = 128, + .page_size = 16, + .flags = EE_ADDR1, +}; + +static struct spi_board_info spi0_board_info[] __initdata = { + { + .modalias = "rtc-ds1390", + .max_speed_hz = 4000000, + .chip_select = 2, + }, + { + .modalias = "at25", + .max_speed_hz = 1000000, + .chip_select = 1, + .mode = SPI_MODE_3, + .platform_data = &eeprom_25lc010, + }, +}; + +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = GPIO_PIN_PA(26), + .wp_pin = GPIO_PIN_PA(27), + }, +}; + +/* + * The next two functions should go away as the boot loader is + * supposed to initialize the macb address registers with a valid + * ethernet address. But we need to keep it around for a while until + * we can be reasonably sure the boot loader does this. + * + * The phy_id is ignored as the driver will probe for it. + */ +static int __init parse_tag_ethernet(struct tag *tag) +{ + int i; + + i = tag->u.ethernet.mac_index; + if (i < ARRAY_SIZE(hw_addr)) + memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, + sizeof(hw_addr[i].addr)); + + return 0; +} +__tagtable(ATAG_ETHERNET, parse_tag_ethernet); + +static void __init set_hw_addr(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const u8 *addr; + void __iomem *regs; + struct clk *pclk; + + if (!res) + return; + if (pdev->id >= ARRAY_SIZE(hw_addr)) + return; + + addr = hw_addr[pdev->id].addr; + if (!is_valid_ether_addr(addr)) + return; + + /* + * Since this is board-specific code, we'll cheat and use the + * physical address directly as we happen to know that it's + * the same as the virtual address. + */ + regs = (void __iomem __force *)res->start; + pclk = clk_get(&pdev->dev, "pclk"); + if (!pclk) + return; + + clk_enable(pclk); + __raw_writel((addr[3] << 24) | (addr[2] << 16) + | (addr[1] << 8) | addr[0], regs + 0x98); + __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); + clk_disable(pclk); + clk_put(pclk); +} + +void __init setup_board(void) +{ + at32_map_usart(0, 0); /* USART 0: /dev/ttyS0 (TTL --> Altera) */ + at32_map_usart(1, 1); /* USART 1: /dev/ttyS1 (RS232) */ + at32_map_usart(2, 2); /* USART 2: /dev/ttyS2 (RS485) */ + at32_map_usart(3, 3); /* USART 3: /dev/ttyS3 (RS422 Multidrop) */ +} + +static struct i2c_gpio_platform_data i2c_gpio_data = { + .sda_pin = GPIO_PIN_PA(6), + .scl_pin = GPIO_PIN_PA(7), + .sda_is_open_drain = 1, + .scl_is_open_drain = 1, + .udelay = 2, /* close to 100 kHz */ +}; + +static struct platform_device i2c_gpio_device = { + .name = "i2c-gpio", + .id = 0, + .dev = { + .platform_data = &i2c_gpio_data, + }, +}; + +static struct i2c_board_info __initdata i2c_info[] = { +}; + +static int __init mimc200_init(void) +{ + /* + * MIMC200 uses 16-bit SDRAM interface, so we don't need to + * reserve any pins for it. + */ + + at32_add_system_devices(); + + at32_add_device_usart(0); + at32_add_device_usart(1); + at32_add_device_usart(2); + at32_add_device_usart(3); + + set_hw_addr(at32_add_device_eth(0, ð_data[0])); + set_hw_addr(at32_add_device_eth(1, ð_data[1])); + + at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); + at32_add_device_mci(0, &mci0_data); + at32_add_device_usba(0, NULL); + + at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP); + at32_select_gpio(i2c_gpio_data.sda_pin, + AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_select_gpio(i2c_gpio_data.scl_pin, + AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + platform_device_register(&i2c_gpio_device); + i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); + + at32_add_device_lcdc(0, &mimc200_lcdc_data, + fbmem_start, fbmem_size, 1); + + return 0; +} +postcore_initcall(mimc200_init); |