diff options
author | Timothy Pearson <tpearson@raptorengineering.com> | 2017-08-23 14:45:25 -0500 |
---|---|---|
committer | Timothy Pearson <tpearson@raptorengineering.com> | 2017-08-23 14:45:25 -0500 |
commit | fcbb27b0ec6dcbc5a5108cb8fb19eae64593d204 (patch) | |
tree | 22962a4387943edc841c72a4e636a068c66d58fd /arch/avr32/boards | |
download | ast2050-linux-kernel-fcbb27b0ec6dcbc5a5108cb8fb19eae64593d204.zip ast2050-linux-kernel-fcbb27b0ec6dcbc5a5108cb8fb19eae64593d204.tar.gz |
Initial import of modified Linux 2.6.28 tree
Original upstream URL:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git | branch linux-2.6.28.y
Diffstat (limited to 'arch/avr32/boards')
21 files changed, 2500 insertions, 0 deletions
diff --git a/arch/avr32/boards/atngw100/Kconfig b/arch/avr32/boards/atngw100/Kconfig new file mode 100644 index 0000000..b3f9947 --- /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 new file mode 100644 index 0000000..6376f53 --- /dev/null +++ b/arch/avr32/boards/atngw100/Makefile @@ -0,0 +1,2 @@ +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 0000000..8140b22 --- /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/flash.c b/arch/avr32/boards/atngw100/flash.c new file mode 100644 index 0000000..55ccc9c --- /dev/null +++ b/arch/avr32/boards/atngw100/flash.c @@ -0,0 +1,98 @@ +/* + * ATNGW100 board-specific flash initialization + * + * Copyright (C) 2005-2006 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 <mach/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 atngw100_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 "atngw100: failed to set NOR flash timing\n"); + return ret; + } + + platform_device_register(&flash_device); + + return 0; +} +device_initcall(atngw100_flash_init); diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c new file mode 100644 index 0000000..32fb9ba --- /dev/null +++ b/arch/avr32/boards/atngw100/setup.c @@ -0,0 +1,228 @@ +/* + * Board-specific setup code for the ATNGW100 Network Gateway + * + * Copyright (C) 2005-2006 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/gpio.h> +#include <linux/irq.h> +#include <linux/i2c.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 <asm/atmel-mci.h> +#include <asm/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] = 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[2]; +static struct eth_platform_data __initdata eth_data[2]; + +static struct spi_board_info spi0_board_info[] __initdata = { + { + .modalias = "mtd_dataflash", + .max_speed_hz = 8000000, + .chip_select = 0, + }, +}; + +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 + }, +}; + +/* + * 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(1, 0); /* USART 1: /dev/ttyS0, DB9 */ + at32_setup_serial_console(0); +} + +static const struct gpio_led ngw_leds[] = { + { .name = "sys", .gpio = GPIO_PIN_PA(16), .active_low = 1, + .default_trigger = "heartbeat", + }, + { .name = "a", .gpio = GPIO_PIN_PA(19), .active_low = 1, }, + { .name = "b", .gpio = GPIO_PIN_PE(19), .active_low = 1, }, +}; + +static const struct gpio_led_platform_data ngw_led_data = { + .num_leds = ARRAY_SIZE(ngw_leds), + .leds = (void *) ngw_leds, +}; + +static struct platform_device ngw_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = (void *) &ngw_led_data, + } +}; + +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[] = { + /* NOTE: original ATtiny24 firmware is at address 0x0b */ +}; + +static int __init atngw100_init(void) +{ + unsigned i; + + /* + * ATNGW100 uses 16-bit SDRAM interface, so we don't need to + * reserve any pins for it. + */ + + at32_add_device_usart(0); + + 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); + + for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) { + at32_select_gpio(ngw_leds[i].gpio, + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + } + platform_device_register(&ngw_gpio_leds); + + /* all these i2c/smbus pins should have external pullups for + * open-drain sharing among all I2C devices. SDA and SCL do; + * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus), + * but it's not available off-board. + */ + 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)); + + return 0; +} +postcore_initcall(atngw100_init); + +static int __init atngw100_arch_init(void) +{ + /* PB30 is the otherwise unused jumper on the mainboard, with an + * external pullup; the jumper grounds it. Use it however you + * like, including letting U-Boot or Linux tweak boot sequences. + */ + at32_select_gpio(GPIO_PIN_PB(30), 0); + gpio_request(GPIO_PIN_PB(30), "j15"); + gpio_direction_input(GPIO_PIN_PB(30)); + gpio_export(GPIO_PIN_PB(30), false); + + /* set_irq_type() after the arch_initcall for EIC has run, and + * before the I2C subsystem could try using this IRQ. + */ + return set_irq_type(AT32_EXTINT(3), IRQ_TYPE_EDGE_FALLING); +} +arch_initcall(atngw100_arch_init); diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig new file mode 100644 index 0000000..8dc4821 --- /dev/null +++ b/arch/avr32/boards/atstk1000/Kconfig @@ -0,0 +1,109 @@ +# STK1000 customization + +if BOARD_ATSTK1000 + +choice + prompt "ATSTK1000 CPU daughterboard type" + default BOARD_ATSTK1002 + +config BOARD_ATSTK1002 + bool "ATSTK1002" + select CPU_AT32AP7000 + +config BOARD_ATSTK1003 + bool "ATSTK1003" + select CPU_AT32AP7001 + +config BOARD_ATSTK1004 + bool "ATSTK1004" + select CPU_AT32AP7002 + +config BOARD_ATSTK1006 + bool "ATSTK1006" + select CPU_AT32AP7000 + +endchoice + + +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_ATSTK100X_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_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_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_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 + PCI-format connector) connect a video sensor. + +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_ATSTK100X_SPI1 + bool "Configure SPI1 controller" + 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" + here to configure that SPI controller. + +config BOARD_ATSTK1000_J2_LED + bool + default BOARD_ATSTK1000_J2_LED8 || BOARD_ATSTK1000_J2_RGB + +choice + prompt "LEDs connected to J2:" + depends on LEDS_GPIO && !BOARD_ATSTK100X_SW4_CUSTOM + optional + help + Select this if you have jumpered the J2 jumper block to the + LED0..LED7 amber leds, or to the RGB leds, using a ten-pin + IDC cable. A default "heartbeat" trigger is provided, but + you can of course override this. + +config BOARD_ATSTK1000_J2_LED8 + bool "LED0..LED7" + help + Select this if J2 is jumpered to LED0..LED7 amber leds. + +config BOARD_ATSTK1000_J2_RGB + bool "RGB leds" + help + Select this if J2 is jumpered to the RGB leds. + +endchoice + +config BOARD_ATSTK1000_EXTDAC + bool + depends on !BOARD_ATSTK100X_SW1_CUSTOM && !BOARD_ATSTK100X_SW3_CUSTOM + default y + +endif # stk 1000 diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile new file mode 100644 index 0000000..edecee0 --- /dev/null +++ b/arch/avr32/boards/atstk1000/Makefile @@ -0,0 +1,5 @@ +obj-y += setup.o flash.o +obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o +obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o +obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o +obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h new file mode 100644 index 0000000..9392d32 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1000.h @@ -0,0 +1,17 @@ +/* + * ATSTK1000 setup code: Daughterboard interface + * + * 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. + */ +#ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H +#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H + +extern struct atmel_lcdfb_info atstk1000_lcdc_data; + +void atstk1000_setup_j2_leds(void); + +#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */ diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c new file mode 100644 index 0000000..5c5cdf3 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -0,0 +1,350 @@ +/* + * ATSTK1002/ATSTK1006 daughterboard-specific init code + * + * Copyright (C) 2005-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/etherdevice.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/spi.h> +#include <linux/spi/at73c213.h> + +#include <video/atmel_lcdc.h> + +#include <asm/io.h> +#include <asm/setup.h> +#include <asm/atmel-mci.h> + +#include <mach/at32ap700x.h> +#include <mach/board.h> +#include <mach/init.h> +#include <mach/portmux.h> + +#include "atstk1000.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 */ +}; + +/* + * The ATSTK1006 daughterboard is very similar to the ATSTK1002. Both + * have the AT32AP7000 chip on board; the difference is that the + * STK1006 has 128 MB SDRAM (the STK1002 uses the 8 MB SDRAM chip on + * the STK1000 motherboard) and 256 MB NAND flash (the STK1002 has + * none.) + * + * The RAM difference is handled by the boot loader, so the only + * difference we end up handling here is the NAND flash. + */ +#ifdef CONFIG_BOARD_ATSTK1006 +#include <linux/mtd/partitions.h> +#include <mach/smc.h> + +static struct smc_timing nand_timing __initdata = { + .ncs_read_setup = 0, + .nrd_setup = 10, + .ncs_write_setup = 0, + .nwe_setup = 10, + + .ncs_read_pulse = 30, + .nrd_pulse = 15, + .ncs_write_pulse = 30, + .nwe_pulse = 15, + + .read_cycle = 30, + .write_cycle = 30, + + .ncs_read_recover = 0, + .nrd_recover = 15, + .ncs_write_recover = 0, + /* WE# high -> RE# low min 60 ns */ + .nwe_recover = 50, +}; + +static struct smc_config nand_config __initdata = { + .bus_width = 1, + .nrd_controlled = 1, + .nwe_controlled = 1, + .nwait_mode = 0, + .byte_write = 0, + .tdf_cycles = 2, + .tdf_mode = 0, +}; + +static struct mtd_partition nand_partitions[] = { + { + .name = "main", + .offset = 0x00000000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_part_info(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(nand_partitions); + return nand_partitions; +} + +static struct atmel_nand_data atstk1006_nand_data __initdata = { + .cle = 21, + .ale = 22, + .rdy_pin = GPIO_PIN_PB(30), + .enable_pin = GPIO_PIN_PB(29), + .partition_info = nand_part_info, +}; +#endif + +struct eth_addr { + u8 addr[6]; +}; + +static struct eth_addr __initdata hw_addr[2]; +static struct eth_platform_data __initdata eth_data[2] = { + { + /* + * The MDIO pullups on STK1000 are a bit too weak for + * the autodetection to work properly, so we have to + * mask out everything but the correct address. + */ + .phy_mask = ~(1U << 16), + }, + { + .phy_mask = ~(1U << 17), + }, +}; + +#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 + +/* + * 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); +} + +#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC +static void __init atstk1002_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_PIOA_BASE, (1 << 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 atstk1002_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); +} + +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM + +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + +/* MMC card detect requires MACB0 *NOT* be used */ +#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM + .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ + .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ +#else + .detect_pin = -ENODEV, + .wp_pin = -ENODEV, +#endif /* SW6 for sd{cd,wp} routing */ + }, +}; + +#endif /* SW2 for MMC signal routing */ + +static int __init atstk1002_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 */ + +#ifdef CONFIG_BOARD_ATSTK1006 + smc_set_timing(&nand_config, &nand_timing); + smc_set_configuration(3, &nand_config); + at32_add_device_nand(0, &atstk1006_nand_data); +#endif + +#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_ATSTK1002_SW6_CUSTOM + set_hw_addr(at32_add_device_eth(0, ð_data[0])); +#endif +#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, &mci0_data); +#endif +#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM + set_hw_addr(at32_add_device_eth(1, ð_data[1])); +#else + at32_add_device_lcdc(0, &atstk1000_lcdc_data, + fbmem_start, fbmem_size, + ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); +#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(); + atstk1002_setup_extdac(); + + return 0; +} +postcore_initcall(atstk1002_init); diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c new file mode 100644 index 0000000..134b566 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -0,0 +1,178 @@ +/* + * 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/atmel-mci.h> + +#include <mach/at32ap700x.h> +#include <mach/board.h> +#include <mach/init.h> +#include <mach/portmux.h> + +#include "atstk1000.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 */ +}; + +#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 + +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = -ENODEV, + .wp_pin = -ENODEV, + }, +}; +#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_PIOA_BASE, (1 << 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 */ + +#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, &mci0_data); +#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..cb32eb8 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -0,0 +1,164 @@ +/* + * 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/atmel-mci.h> + +#include <mach/at32ap700x.h> +#include <mach/board.h> +#include <mach/init.h> +#include <mach/portmux.h> + +#include "atstk1000.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 */ +}; + +#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 + +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = -ENODEV, + .wp_pin = -ENODEV, + }, +}; +#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_PIOA_BASE, (1 << 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) +{ +#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, &mci0_data); +#endif + at32_add_device_lcdc(0, &atstk1000_lcdc_data, + fbmem_start, fbmem_size, + ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); + 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); diff --git a/arch/avr32/boards/atstk1000/flash.c b/arch/avr32/boards/atstk1000/flash.c new file mode 100644 index 0000000..6e4d561 --- /dev/null +++ b/arch/avr32/boards/atstk1000/flash.c @@ -0,0 +1,98 @@ +/* + * ATSTK1000 board-specific flash initialization + * + * Copyright (C) 2005-2006 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 <mach/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 atstk1000_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 "atstk1000: failed to set NOR flash timing\n"); + return ret; + } + + platform_device_register(&flash_device); + + return 0; +} +device_initcall(atstk1000_flash_init); diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c new file mode 100644 index 0000000..2d6b560 --- /dev/null +++ b/arch/avr32/boards/atstk1000/setup.c @@ -0,0 +1,127 @@ +/* + * ATSTK1000 board-specific setup code. + * + * Copyright (C) 2005-2006 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/bootmem.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/linkage.h> + +#include <video/atmel_lcdc.h> + +#include <asm/setup.h> + +#include <mach/at32ap700x.h> +#include <mach/board.h> +#include <mach/portmux.h> + +#include "atstk1000.h" + +/* Initialized by bootloader-specific startup code. */ +struct tag *bootloader_tags __initdata; + +static struct fb_videomode __initdata ltv350qv_modes[] = { + { + .name = "320x240 @ 75", + .refresh = 75, + .xres = 320, .yres = 240, + .pixclock = KHZ2PICOS(6891), + + .left_margin = 17, .right_margin = 33, + .upper_margin = 10, .lower_margin = 10, + .hsync_len = 16, .vsync_len = 1, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata atstk1000_default_monspecs = { + .manufacturer = "SNG", + .monitor = "LTV350QV", + .modedb = ltv350qv_modes, + .modedb_len = ARRAY_SIZE(ltv350qv_modes), + .hfmin = 14820, + .hfmax = 22230, + .vfmin = 60, + .vfmax = 90, + .dclkmax = 30000000, +}; + +struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = { + .default_bpp = 24, + .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 = &atstk1000_default_monspecs, + .guard_time = 2, +}; + +#ifdef CONFIG_BOARD_ATSTK1000_J2_LED +#include <linux/leds.h> + +static struct gpio_led stk1000_j2_led[] = { +#ifdef CONFIG_BOARD_ATSTK1000_J2_LED8 +#define LEDSTRING "J2 jumpered to LED8" + { .name = "led0:amber", .gpio = GPIO_PIN_PB( 8), }, + { .name = "led1:amber", .gpio = GPIO_PIN_PB( 9), }, + { .name = "led2:amber", .gpio = GPIO_PIN_PB(10), }, + { .name = "led3:amber", .gpio = GPIO_PIN_PB(13), }, + { .name = "led4:amber", .gpio = GPIO_PIN_PB(14), }, + { .name = "led5:amber", .gpio = GPIO_PIN_PB(15), }, + { .name = "led6:amber", .gpio = GPIO_PIN_PB(16), }, + { .name = "led7:amber", .gpio = GPIO_PIN_PB(30), + .default_trigger = "heartbeat", }, +#else /* RGB */ +#define LEDSTRING "J2 jumpered to RGB LEDs" + { .name = "r1:red", .gpio = GPIO_PIN_PB( 8), }, + { .name = "g1:green", .gpio = GPIO_PIN_PB(10), }, + { .name = "b1:blue", .gpio = GPIO_PIN_PB(14), }, + + { .name = "r2:red", .gpio = GPIO_PIN_PB( 9), + .default_trigger = "heartbeat", }, + { .name = "g2:green", .gpio = GPIO_PIN_PB(13), }, + { .name = "b2:blue", .gpio = GPIO_PIN_PB(15), + .default_trigger = "heartbeat", }, + /* PB16, PB30 unused */ +#endif +}; + +static struct gpio_led_platform_data stk1000_j2_led_data = { + .num_leds = ARRAY_SIZE(stk1000_j2_led), + .leds = stk1000_j2_led, +}; + +static struct platform_device stk1000_j2_led_dev = { + .name = "leds-gpio", + .id = 2, /* gpio block J2 */ + .dev = { + .platform_data = &stk1000_j2_led_data, + }, +}; + +void __init atstk1000_setup_j2_leds(void) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(stk1000_j2_led); i++) + at32_select_gpio(stk1000_j2_led[i].gpio, AT32_GPIOF_OUTPUT); + + printk("STK1000: " LEDSTRING "\n"); + platform_device_register(&stk1000_j2_led_dev); +} +#else /* CONFIG_BOARD_ATSTK1000_J2_LED */ +void __init atstk1000_setup_j2_leds(void) +{ + +} +#endif /* CONFIG_BOARD_ATSTK1000_J2_LED */ diff --git a/arch/avr32/boards/favr-32/Kconfig b/arch/avr32/boards/favr-32/Kconfig new file mode 100644 index 0000000..2c83d1d --- /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 0000000..234f215 --- /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 0000000..604bbd5 --- /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 <mach/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 0000000..1ee4faf --- /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 <mach/at32ap700x.h> +#include <mach/init.h> +#include <mach/board.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] = 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 0000000..79c076e --- /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 0000000..d83d650 --- /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 0000000..54fbd95 --- /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 0000000..397cbb8 --- /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); |