avr32: remove support for AVR32 architecture

This patch drops support for AVR32 architecture from the Linux kernel.

The AVR32 architecture is not keeping up with the development of the
kernel, and since it shares so much of the drivers with Atmel ARM SoC,
it is starting to hinder these drivers to develop swiftly.

Also, all AVR32 AP7 SoC processors are end of lifed from Atmel (now
Microchip).

Finally, the GCC toolchain is stuck at version 4.2.x, and has not
received any patches since the last release from Atmel;
4.2.4-atmel.1.1.3.avr32linux.1. When building kernel v4.10, this
toolchain is no longer able to properly link the network stack.

Haavard and I have came to the conclusion that we feel keeping AVR32 on
life support offers more obstacles for Atmel ARMs, than it gives joy to
AVR32 users. I also suspect there are very few AVR32 users left today,
if anybody at all.
Signed-off-by: NHans-Christian Noren Egtvedt <egtvedt@samfundet.no>
Signed-off-by: NHåvard Skinnemoen <hskinnemoen@gmail.com>
Signed-off-by: NNicolas Ferre <nicolas.ferre@microchip.com>
Acked-by: NAndy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: NBoris Brezillon <boris.brezillon@free-electrons.com>
上级 a351e9b9
......@@ -1034,6 +1034,10 @@ S: 2037 Walnut #6
S: Boulder, Colorado 80302
S: USA
N: Hans-Christian Noren Egtvedt
E: egtvedt@samfundet.no
D: AVR32 architecture maintainer.
N: Heiko Eißfeldt
E: heiko@colossus.escape.de heiko@unifix.de
D: verify_area stuff, generic SCSI fixes
......@@ -3398,6 +3402,10 @@ S: Suite 101
S: Markham, Ontario L3R 2Z6
S: Canada
N: Haavard Skinnemoen
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
D: AVR32 architecture port to Linux and maintainer.
N: Rick Sladkey
E: jrs@world.std.com
D: utility hacker: Emacs, NFS server, mount, kmem-ps, UPS debugger, strace, GDB
......
......@@ -2327,21 +2327,6 @@ S: Maintained
F: drivers/auxdisplay/
F: include/linux/cfag12864b.h
AVR32 ARCHITECTURE
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
M: Hans-Christian Egtvedt <egtvedt@samfundet.no>
W: http://www.atmel.com/products/AVR32/
W: http://mirror.egtvedt.no/avr32linux.org/
W: http://avrfreaks.net/
S: Maintained
F: arch/avr32/
AVR32/AT32AP MACHINE SUPPORT
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
M: Hans-Christian Egtvedt <egtvedt@samfundet.no>
S: Maintained
F: arch/avr32/mach-at32ap/
AX.25 NETWORK LAYER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-hams@vger.kernel.org
......
config AVR32
def_bool y
# With EXPERT=n, we get lots of stuff automatically selected
# that we usually don't need on AVR32.
select EXPERT
select HAVE_CLK
select HAVE_EXIT_THREAD
select HAVE_OPROFILE
select HAVE_KPROBES
select VIRT_TO_BUS
select GENERIC_IRQ_PROBE
select GENERIC_ATOMIC64
select HARDIRQS_SW_RESEND
select GENERIC_IRQ_SHOW
select ARCH_HAVE_CUSTOM_GPIO_H
select ARCH_WANT_IPC_PARSE_VERSION
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_CLOCKEVENTS
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
select HAVE_NMI
help
AVR32 is a high-performance 32-bit RISC microprocessor core,
designed for cost-sensitive embedded applications, with particular
emphasis on low power consumption and high code density.
There is an AVR32 Linux project with a web page at
http://avr32linux.org/.
config STACKTRACE_SUPPORT
def_bool y
config LOCKDEP_SUPPORT
def_bool y
config TRACE_IRQFLAGS_SUPPORT
def_bool y
config RWSEM_GENERIC_SPINLOCK
def_bool y
config RWSEM_XCHGADD_ALGORITHM
def_bool n
config ARCH_HAS_ILOG2_U32
def_bool n
config ARCH_HAS_ILOG2_U64
def_bool n
config GENERIC_HWEIGHT
def_bool y
config GENERIC_CALIBRATE_DELAY
def_bool y
config GENERIC_BUG
def_bool y
depends on BUG
source "init/Kconfig"
source "kernel/Kconfig.freezer"
menu "System Type and features"
config SUBARCH_AVR32B
bool
config MMU
bool
config PERFORMANCE_COUNTERS
bool
config PLATFORM_AT32AP
bool
select SUBARCH_AVR32B
select MMU
select PERFORMANCE_COUNTERS
select GPIOLIB
select GENERIC_ALLOCATOR
select HAVE_FB_ATMEL
#
# CPU types
#
# AP7000 derivatives
config CPU_AT32AP700X
bool
select PLATFORM_AT32AP
config CPU_AT32AP7000
bool
select CPU_AT32AP700X
config CPU_AT32AP7001
bool
select CPU_AT32AP700X
config CPU_AT32AP7002
bool
select CPU_AT32AP700X
# AP700X boards
config BOARD_ATNGW100_COMMON
bool
select CPU_AT32AP7000
choice
prompt "AVR32 board type"
default BOARD_ATSTK1000
config BOARD_ATSTK1000
bool "ATSTK1000 evaluation board"
config BOARD_ATNGW100_MKI
bool "ATNGW100 Network Gateway"
select BOARD_ATNGW100_COMMON
config BOARD_ATNGW100_MKII
bool "ATNGW100 mkII Network Gateway"
select BOARD_ATNGW100_COMMON
config BOARD_HAMMERHEAD
bool "Hammerhead board"
select CPU_AT32AP7000
select USB_ARCH_HAS_HCD
help
The Hammerhead platform is built around an AVR32 32-bit microcontroller from Atmel.
It offers versatile peripherals, such as ethernet, usb device, usb host etc.
The board also incorporates a power supply and is a Power over Ethernet (PoE) Powered
Device (PD).
Additionally, a Cyclone III FPGA from Altera is integrated on the board. The FPGA is
mapped into the 32-bit AVR memory bus. The FPGA offers two DDR2 SDRAM interfaces, which
will cover even the most exceptional need of memory bandwidth. Together with the onboard
video decoder the board is ready for video processing.
For more information see: http://www.miromico.ch/index.php/hammerhead.html
config BOARD_FAVR_32
bool "Favr-32 LCD-board"
select CPU_AT32AP7000
config BOARD_MERISC
bool "Merisc board"
select CPU_AT32AP7000
help
Merisc is the family name for a range of AVR32-based boards.
The boards are designed to be used in a man-machine
interfacing environment, utilizing a touch-based graphical
user interface. They host a vast range of I/O peripherals as
well as a large SDRAM & Flash memory bank.
For more information see: http://www.martinsson.se/merisc
config BOARD_MIMC200
bool "MIMC200 CPU board"
select CPU_AT32AP7000
endchoice
source "arch/avr32/boards/atstk1000/Kconfig"
source "arch/avr32/boards/atngw100/Kconfig"
source "arch/avr32/boards/hammerhead/Kconfig"
source "arch/avr32/boards/favr-32/Kconfig"
source "arch/avr32/boards/merisc/Kconfig"
choice
prompt "Boot loader type"
default LOADER_U_BOOT
config LOADER_U_BOOT
bool "U-Boot (or similar) bootloader"
endchoice
source "arch/avr32/mach-at32ap/Kconfig"
config LOAD_ADDRESS
hex
default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP700X=y
config ENTRY_ADDRESS
hex
default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP700X=y
config PHYS_OFFSET
hex
default 0x10000000 if CPU_AT32AP700X=y
source "kernel/Kconfig.preempt"
config QUICKLIST
def_bool y
config ARCH_HAVE_MEMORY_PRESENT
def_bool n
config NEED_NODE_MEMMAP_SIZE
def_bool n
config ARCH_FLATMEM_ENABLE
def_bool y
config ARCH_DISCONTIGMEM_ENABLE
def_bool n
config ARCH_SPARSEMEM_ENABLE
def_bool n
config NODES_SHIFT
int
default "2"
depends on NEED_MULTIPLE_NODES
source "mm/Kconfig"
config OWNERSHIP_TRACE
bool "Ownership trace support"
default y
help
Say Y to generate an Ownership Trace message on every context switch,
enabling Nexus-compliant debuggers to keep track of the PID of the
currently executing task.
config NMI_DEBUGGING
bool "NMI Debugging"
default n
help
Say Y here and pass the nmi_debug command-line parameter to
the kernel to turn on NMI debugging. Depending on the value
of the nmi_debug option, various pieces of information will
be dumped to the console when a Non-Maskable Interrupt
happens.
# FPU emulation goes here
source "kernel/Kconfig.hz"
config CMDLINE
string "Default kernel command line"
default ""
help
If you don't have a boot loader capable of passing a command line string
to the kernel, you may specify one here. As a minimum, you should specify
the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
endmenu
menu "Power management options"
source "kernel/power/Kconfig"
config ARCH_SUSPEND_POSSIBLE
def_bool y
menu "CPU Frequency scaling"
source "drivers/cpufreq/Kconfig"
endmenu
endmenu
menu "Bus options"
config PCI
bool
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
endmenu
menu "Executable file formats"
source "fs/Kconfig.binfmt"
endmenu
source "net/Kconfig"
source "drivers/Kconfig"
source "fs/Kconfig"
source "arch/avr32/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
menu "Kernel hacking"
config TRACE_IRQFLAGS_SUPPORT
bool
default y
source "lib/Kconfig.debug"
endmenu
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2004-2006 Atmel Corporation.
# Default target when executing plain make
.PHONY: all
all: uImage vmlinux.elf
KBUILD_DEFCONFIG := atstk1002_defconfig
KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic -D__linux__
KBUILD_AFLAGS += -mrelax -mno-pic
KBUILD_CFLAGS_MODULE += -mno-relax
LDFLAGS_vmlinux += --relax
cpuflags-$(CONFIG_PLATFORM_AT32AP) += -march=ap
KBUILD_CFLAGS += $(cpuflags-y)
KBUILD_AFLAGS += $(cpuflags-y)
CHECKFLAGS += -D__avr32__ -D__BIG_ENDIAN
machine-$(CONFIG_PLATFORM_AT32AP) := at32ap
machdirs := $(patsubst %,arch/avr32/mach-%/, $(machine-y))
KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o
head-y += arch/avr32/kernel/head.o
core-y += $(machdirs)
core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
core-$(CONFIG_BOARD_ATNGW100_COMMON) += arch/avr32/boards/atngw100/
core-$(CONFIG_BOARD_HAMMERHEAD) += arch/avr32/boards/hammerhead/
core-$(CONFIG_BOARD_FAVR_32) += arch/avr32/boards/favr-32/
core-$(CONFIG_BOARD_MERISC) += arch/avr32/boards/merisc/
core-$(CONFIG_BOARD_MIMC200) += arch/avr32/boards/mimc200/
core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
core-y += arch/avr32/kernel/
core-y += arch/avr32/mm/
drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/
libs-y += arch/avr32/lib/
BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec
.PHONY: $(BOOT_TARGETS) install
boot := arch/$(ARCH)/boot/images
KBUILD_IMAGE := $(boot)/uImage
vmlinux.elf: KBUILD_IMAGE := $(boot)/vmlinux.elf
vmlinux.cso: KBUILD_IMAGE := $(boot)/vmlinux.cso
uImage.srec: KBUILD_IMAGE := $(boot)/uImage.srec
uImage: KBUILD_IMAGE := $(boot)/uImage
quiet_cmd_listing = LST $@
cmd_listing = avr32-linux-objdump $(OBJDUMPFLAGS) -lS $< > $@
quiet_cmd_disasm = DIS $@
cmd_disasm = avr32-linux-objdump $(OBJDUMPFLAGS) -d $< > $@
vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
install: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
vmlinux.s: vmlinux
$(call if_changed,disasm)
vmlinux.lst: vmlinux
$(call if_changed,listing)
CLEAN_FILES += vmlinux.s vmlinux.lst
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
define archhelp
@echo '* vmlinux.elf - ELF image with load address 0'
@echo ' vmlinux.cso - PathFinder CSO image'
@echo '* uImage - Create a bootable image for U-Boot'
endef
# NGW100 customization
if BOARD_ATNGW100_COMMON
config BOARD_ATNGW100_MKII_LCD
bool "Enable ATNGW100 mkII LCD interface"
depends on BOARD_ATNGW100_MKII
help
This enables the LCD controller (LCDC) in the AT32AP7000. Since the
LCDC is multiplexed with MACB1 (LAN) Ethernet port, only one can be
enabled at a time.
This choice enables the LCDC and disables the MACB1 interface marked
LAN on the PCB.
choice
prompt "Select an NGW100 add-on board to support"
default BOARD_ATNGW100_ADDON_NONE
config BOARD_ATNGW100_ADDON_NONE
bool "None"
config BOARD_ATNGW100_EVKLCD10X
bool "EVKLCD10X addon board"
depends on BOARD_ATNGW100_MKI || BOARD_ATNGW100_MKII_LCD
help
This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA)
addon board for the NGW100 and NGW100 mkII. By enabling this the LCD
controller and AC97 controller is added as platform devices.
config BOARD_ATNGW100_MRMT
bool "Mediama RMT1/2 add-on board"
help
This enables support for the Mediama RMT1 or RMT2 board.
RMT provides LCD support, AC97 codec and other
optional peripherals to the Atmel NGW100.
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.
endchoice
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
if BOARD_ATNGW100_MRMT
source "arch/avr32/boards/atngw100/Kconfig_mrmt"
endif
endif # BOARD_ATNGW100_COMMON
# RMT for NGW100 customization
choice
prompt "RMT Version"
help
Select the RMTx board version.
config BOARD_MRMT_REV1
bool "RMT1"
config BOARD_MRMT_REV2
bool "RMT2"
endchoice
config BOARD_MRMT_AC97
bool "Enable AC97 CODEC"
help
Enable the UCB1400 AC97 CODEC driver.
choice
prompt "Touchscreen Driver"
default BOARD_MRMT_ADS7846_TS
config BOARD_MRMT_UCB1400_TS
bool "Use UCB1400 Touchscreen"
config BOARD_MRMT_ADS7846_TS
bool "Use ADS7846 Touchscreen"
endchoice
choice
prompt "RMTx LCD Selection"
default BOARD_MRMT_LCD_DISABLE
config BOARD_MRMT_LCD_DISABLE
bool "LCD Disabled"
config BOARD_MRMT_LCD_LQ043T3DX0X
bool "Sharp LQ043T3DX0x or compatible"
help
If using RMT2, be sure to load the resistor pack selectors accordingly
if BOARD_MRMT_REV2
config BOARD_MRMT_LCD_KWH043GM08
bool "Formike KWH043GM08 or compatible"
help
Be sure to load the RMT2 resistor pack selectors accordingly
endif
endchoice
if !BOARD_MRMT_LCD_DISABLE
config BOARD_MRMT_BL_PWM
bool "Use PWM control for LCD Backlight"
help
Use PWM driver for controlling LCD Backlight.
Otherwise, LCD Backlight is always on.
endif
config BOARD_MRMT_RTC_I2C
bool "Use External RTC on I2C Bus"
help
RMT1 has an optional RTC device on the I2C bus.
It is a SII S35390A. Be sure to select the
matching RTC driver.
choice
prompt "Wireless Module on ttyS2"
default BOARD_MRMT_WIRELESS_ZB
config BOARD_MRMT_WIRELESS_ZB
bool "Use ZigBee/802.15.4 Module"
config BOARD_MRMT_WIRELESS_BT
bool "Use Bluetooth (HCI) Module"
config BOARD_MRMT_WIRELESS_NONE
bool "Not Installed"
endchoice
obj-y += setup.o flash.o
obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X) += evklcd10x.o
obj-$(CONFIG_BOARD_ATNGW100_MRMT) += mrmt.o
/*
* 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/gpio.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/portmux.h>
#include <mach/board.h>
#include <sound/atmel-ac97c.h>
static struct ac97c_platform_data __initdata ac97c0_data = {
.reset_pin = GPIO_PIN_PB(19),
};
#ifdef CONFIG_BOARD_ATNGW100_EVKLCD10X_VGA
static struct fb_videomode __initdata tcg057vglad_modes[] = {
{
.name = "640x480 @ 50",
.refresh = 50,
.xres = 640, .yres = 480,
.pixclock = KHZ2PICOS(25180),
.left_margin = 64, .right_margin = 96,
.upper_margin = 34, .lower_margin = 11,
.hsync_len = 64, .vsync_len = 15,
.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_pdata __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 @ 50",
.refresh = 50,
.xres = 320, .yres = 240,
.pixclock = KHZ2PICOS(6300),
.left_margin = 34, .right_margin = 46,
.upper_margin = 7, .lower_margin = 15,
.hsync_len = 64, .vsync_len = 12,
.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_pdata __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_pdata __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 void atevklcd10x_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
{
gpio_set_value(GPIO_PIN_PB(15), on);
}
static int __init atevklcd10x_init(void)
{
/* PB15 is connected to the enable line on the boost regulator
* controlling the backlight for the LCD panel.
*/
at32_select_gpio(GPIO_PIN_PB(15), AT32_GPIOF_OUTPUT);
gpio_request(GPIO_PIN_PB(15), "backlight");
gpio_direction_output(GPIO_PIN_PB(15), 0);
atevklcd10x_lcdc_data.atmel_lcdfb_power_control =
atevklcd10x_lcdc_power_control;
at32_add_device_lcdc(0, &atevklcd10x_lcdc_data,
fbmem_start, fbmem_size,
#ifdef CONFIG_BOARD_ATNGW100_MKII
ATMEL_LCDC_PRI_18BIT | ATMEL_LCDC_PC_DVAL
#else
ATMEL_LCDC_ALT_18BIT | ATMEL_LCDC_PE_DVAL
#endif
);
at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH);
return 0;
}
postcore_initcall(atevklcd10x_init);
/*
* 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);
/*
* Board-specific setup code for Remote Media Terminal 1 (RMT1)
* add-on board for the ATNGW100 Network Gateway
*
* Copyright (C) 2008 Mediama Technologies
* Based on ATNGW100 Network Gateway (Copyright (C) Atmel)
*
* 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/gpio.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/linkage.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/leds.h>
#include <linux/pwm.h>
#include <linux/leds_pwm.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <video/atmel_lcdc.h>
#include <sound/atmel-ac97c.h>
#include <asm/delay.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>
/* Define board-specifoic GPIO assignments */
#define PIN_LCD_BL GPIO_PIN_PA(28)
#define PWM_CH_BL 0 /* Must match with GPIO pin definition */
#define PIN_LCD_DISP GPIO_PIN_PA(31)
#define PIN_AC97_RST_N GPIO_PIN_PA(30)
#define PB_EXTINT_BASE 25
#define TS_IRQ 0
#define PIN_TS_EXTINT GPIO_PIN_PB(PB_EXTINT_BASE+TS_IRQ)
#define PIN_PB_LEFT GPIO_PIN_PB(11)
#define PIN_PB_RIGHT GPIO_PIN_PB(12)
#define PIN_PWR_SW_N GPIO_PIN_PB(14)
#define PIN_PWR_ON GPIO_PIN_PB(13)
#define PIN_ZB_RST_N GPIO_PIN_PA(21)
#define PIN_BT_RST GPIO_PIN_PA(22)
#define PIN_LED_SYS GPIO_PIN_PA(16)
#define PIN_LED_A GPIO_PIN_PA(19)
#define PIN_LED_B GPIO_PIN_PE(19)
#ifdef CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X
/* Sharp LQ043T3DX0x (or compatible) panel */
static struct fb_videomode __initdata lcd_fb_modes[] = {
{
.name = "480x272 @ 59.94Hz",
.refresh = 59.94,
.xres = 480, .yres = 272,
.pixclock = KHZ2PICOS(9000),
.left_margin = 2, .right_margin = 2,
.upper_margin = 3, .lower_margin = 9,
.hsync_len = 41, .vsync_len = 1,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
};
static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
.manufacturer = "SHA",
.monitor = "LQ043T3DX02",
.modedb = lcd_fb_modes,
.modedb_len = ARRAY_SIZE(lcd_fb_modes),
.hfmin = 14915,
.hfmax = 17638,
.vfmin = 53,
.vfmax = 61,
.dclkmax = 9260000,
};
static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
| ATMEL_LCDC_INVCLK_NORMAL
| ATMEL_LCDC_MEMOR_BIG),
.lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB,
.default_monspecs = &lcd_fb_default_monspecs,
.guard_time = 2,
};
#endif
#ifdef CONFIG_BOARD_MRMT_LCD_KWH043GM08
/* Sharp KWH043GM08-Fxx (or compatible) panel */
static struct fb_videomode __initdata lcd_fb_modes[] = {
{
.name = "480x272 @ 59.94Hz",
.refresh = 59.94,
.xres = 480, .yres = 272,
.pixclock = KHZ2PICOS(9000),
.left_margin = 2, .right_margin = 2,
.upper_margin = 3, .lower_margin = 9,
.hsync_len = 41, .vsync_len = 1,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
};
static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
.manufacturer = "FOR",
.monitor = "KWH043GM08",
.modedb = lcd_fb_modes,
.modedb_len = ARRAY_SIZE(lcd_fb_modes),
.hfmin = 14915,
.hfmax = 17638,
.vfmin = 53,
.vfmax = 61,
.dclkmax = 9260000,
};
static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
| ATMEL_LCDC_INVCLK_INVERTED
| ATMEL_LCDC_MEMOR_BIG),
.lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB,
.default_monspecs = &lcd_fb_default_monspecs,
.guard_time = 2,
};
#endif
#ifdef CONFIG_BOARD_MRMT_AC97
static struct ac97c_platform_data __initdata ac97c0_data = {
.reset_pin = PIN_AC97_RST_N,
};
#endif
#ifdef CONFIG_BOARD_MRMT_UCB1400_TS
/* NOTE: IRQ assignment relies on kernel module parameter */
static struct platform_device rmt_ts_device = {
.name = "ucb1400_ts",
.id = -1,
};
#endif
#ifdef CONFIG_BOARD_MRMT_BL_PWM
/* PWM LEDs: LCD Backlight, etc */
static struct pwm_lookup pwm_lookup[] = {
PWM_LOOKUP("at91sam9rl-pwm", PWM_CH_BL, "leds_pwm", "ds1",
5000, PWM_POLARITY_INVERSED),
};
static struct led_pwm pwm_leds[] = {
{
.name = "backlight",
.max_brightness = 255,
},
};
static struct led_pwm_platform_data pwm_data = {
.num_leds = ARRAY_SIZE(pwm_leds),
.leds = pwm_leds,
};
static struct platform_device leds_pwm = {
.name = "leds_pwm",
.id = -1,
.dev = {
.platform_data = &pwm_data,
},
};
#endif
#ifdef CONFIG_BOARD_MRMT_ADS7846_TS
static int ads7846_pendown_state(void)
{
return !gpio_get_value( PIN_TS_EXTINT ); /* PENIRQ.*/
}
static struct ads7846_platform_data ads_info = {
.model = 7846,
.keep_vref_on = 0, /* Use external VREF pin */
.vref_delay_usecs = 0,
.vref_mv = 3300, /* VREF = 3.3V */
.settle_delay_usecs = 800,
.penirq_recheck_delay_usecs = 800,
.x_plate_ohms = 750,
.y_plate_ohms = 300,
.pressure_max = 4096,
.debounce_max = 1,
.debounce_rep = 0,
.debounce_tol = (~0),
.get_pendown_state = ads7846_pendown_state,
.filter = NULL,
.filter_init = NULL,
};
static struct spi_board_info spi01_board_info[] __initdata = {
{
.modalias = "ads7846",
.max_speed_hz = 31250*26,
.bus_num = 0,
.chip_select = 1,
.platform_data = &ads_info,
.irq = AT32_EXTINT(TS_IRQ),
},
};
#endif
/* GPIO Keys: left, right, power, etc */
static const struct gpio_keys_button rmt_gpio_keys_buttons[] = {
[0] = {
.type = EV_KEY,
.code = KEY_POWER,
.gpio = PIN_PWR_SW_N,
.active_low = 1,
.desc = "power button",
},
[1] = {
.type = EV_KEY,
.code = KEY_LEFT,
.gpio = PIN_PB_LEFT,
.active_low = 1,
.desc = "left button",
},
[2] = {
.type = EV_KEY,
.code = KEY_RIGHT,
.gpio = PIN_PB_RIGHT,
.active_low = 1,
.desc = "right button",
},
};
static const struct gpio_keys_platform_data rmt_gpio_keys_data = {
.nbuttons = ARRAY_SIZE(rmt_gpio_keys_buttons),
.buttons = (void *) rmt_gpio_keys_buttons,
};
static struct platform_device rmt_gpio_keys = {
.name = "gpio-keys",
.id = -1,
.dev = {
.platform_data = (void *) &rmt_gpio_keys_data,
}
};
#ifdef CONFIG_BOARD_MRMT_RTC_I2C
static struct i2c_board_info __initdata mrmt1_i2c_rtc = {
I2C_BOARD_INFO("s35390a", 0x30),
.irq = 0,
};
#endif
static void mrmt_power_off(void)
{
/* PWR_ON=0 will force power off */
gpio_set_value( PIN_PWR_ON, 0 );
}
static int __init mrmt1_init(void)
{
gpio_set_value( PIN_PWR_ON, 1 ); /* Ensure PWR_ON is enabled */
pm_power_off = mrmt_power_off;
/* Setup USARTS (other than console) */
at32_map_usart(2, 1, 0); /* USART 2: /dev/ttyS1, RMT1:DB9M */
at32_map_usart(3, 2, ATMEL_USART_RTS | ATMEL_USART_CTS);
/* USART 3: /dev/ttyS2, RMT1:Wireless, w/ RTS/CTS */
at32_add_device_usart(1);
at32_add_device_usart(2);
/* Select GPIO Key pins */
at32_select_gpio( PIN_PWR_SW_N, AT32_GPIOF_DEGLITCH);
at32_select_gpio( PIN_PB_LEFT, AT32_GPIOF_DEGLITCH);
at32_select_gpio( PIN_PB_RIGHT, AT32_GPIOF_DEGLITCH);
platform_device_register(&rmt_gpio_keys);
#ifdef CONFIG_BOARD_MRMT_RTC_I2C
i2c_register_board_info(0, &mrmt1_i2c_rtc, 1);
#endif
#ifndef CONFIG_BOARD_MRMT_LCD_DISABLE
/* User "alternate" LCDC inferface on Port E & D */
/* NB: exclude LCDC_CC pin, as NGW100 reserves it for other use */
at32_add_device_lcdc(0, &rmt_lcdc_data,
fbmem_start, fbmem_size,
(ATMEL_LCDC_ALT_24BIT | ATMEL_LCDC_PE_DVAL ) );
#endif
#ifdef CONFIG_BOARD_MRMT_AC97
at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH);
#endif
#ifdef CONFIG_BOARD_MRMT_ADS7846_TS
/* Select the Touchscreen interrupt pin mode */
at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ),
GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
irq_set_irq_type(AT32_EXTINT(TS_IRQ), IRQ_TYPE_EDGE_FALLING);
at32_spi_setup_slaves(0,spi01_board_info,ARRAY_SIZE(spi01_board_info));
spi_register_board_info(spi01_board_info,ARRAY_SIZE(spi01_board_info));
#endif
#ifdef CONFIG_BOARD_MRMT_UCB1400_TS
/* Select the Touchscreen interrupt pin mode */
at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ),
GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
platform_device_register(&rmt_ts_device);
#endif
at32_select_gpio( PIN_LCD_DISP, AT32_GPIOF_OUTPUT );
gpio_request( PIN_LCD_DISP, "LCD_DISP" );
gpio_direction_output( PIN_LCD_DISP, 0 ); /* LCD DISP */
#ifdef CONFIG_BOARD_MRMT_LCD_DISABLE
/* Keep Backlight and DISP off */
at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT );
gpio_request( PIN_LCD_BL, "LCD_BL" );
gpio_direction_output( PIN_LCD_BL, 0 ); /* Backlight */
#else
gpio_set_value( PIN_LCD_DISP, 1 ); /* DISP asserted first */
#ifdef CONFIG_BOARD_MRMT_BL_PWM
/* Use PWM for Backlight controls */
at32_add_device_pwm(1 << PWM_CH_BL);
pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
platform_device_register(&leds_pwm);
#else
/* Backlight always on */
udelay( 1 );
at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT );
gpio_request( PIN_LCD_BL, "LCD_BL" );
gpio_direction_output( PIN_LCD_BL, 1 );
#endif
#endif
/* Make sure BT and Zigbee modules in reset */
at32_select_gpio( PIN_BT_RST, AT32_GPIOF_OUTPUT );
gpio_request( PIN_BT_RST, "BT_RST" );
gpio_direction_output( PIN_BT_RST, 1 );
/* BT Module in Reset */
at32_select_gpio( PIN_ZB_RST_N, AT32_GPIOF_OUTPUT );
gpio_request( PIN_ZB_RST_N, "ZB_RST_N" );
gpio_direction_output( PIN_ZB_RST_N, 0 );
/* XBee Module in Reset */
#ifdef CONFIG_BOARD_MRMT_WIRELESS_ZB
udelay( 1000 );
/* Unreset the XBee Module */
gpio_set_value( PIN_ZB_RST_N, 1 );
#endif
#ifdef CONFIG_BOARD_MRMT_WIRELESS_BT
udelay( 1000 );
/* Unreset the BT Module */
gpio_set_value( PIN_BT_RST, 0 );
#endif
return 0;
}
arch_initcall(mrmt1_init);
static int __init mrmt1_early_init(void)
{
/* To maintain power-on signal in case boot loader did not already */
at32_select_gpio( PIN_PWR_ON, AT32_GPIOF_OUTPUT );
gpio_request( PIN_PWR_ON, "PIN_PWR_ON" );
gpio_direction_output( PIN_PWR_ON, 1 );
return 0;
}
core_initcall(mrmt1_early_init);
/*
* 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 <linux/atmel-mci.h>
#include <linux/usb/atmel_usba_udc.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 */
};
/*
* The ATNGW100 mkII is very similar to the ATNGW100. Both have the AT32AP7000
* chip on board; the difference is that the ATNGW100 mkII has 128 MB 32-bit
* SDRAM (the ATNGW100 has 32 MB 16-bit SDRAM) and 256 MB 16-bit NAND flash
* (the ATNGW100 has none.)
*
* The RAM difference is handled by the boot loader, so the only difference we
* end up handling here is the NAND flash, EBI pin reservation and if LCDC or
* MACB1 should be enabled.
*/
#ifdef CONFIG_BOARD_ATNGW100_MKII
#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 = 2,
.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 atmel_nand_data atngw100mkii_nand_data __initdata = {
.cle = 21,
.ale = 22,
.rdy_pin = GPIO_PIN_PB(28),
.enable_pin = GPIO_PIN_PE(23),
.bus_width_16 = true,
.ecc_mode = NAND_ECC_SOFT,
.parts = nand_partitions,
.num_parts = ARRAY_SIZE(nand_partitions),
};
#endif
/* 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 macb_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,
#if defined(CONFIG_BOARD_ATNGW100_MKII)
.detect_pin = GPIO_PIN_PC(25),
.wp_pin = GPIO_PIN_PE(22),
#else
.detect_pin = GPIO_PIN_PC(25),
.wp_pin = GPIO_PIN_PE(0),
#endif
},
};
static struct usba_platform_data atngw100_usba_data __initdata = {
#if defined(CONFIG_BOARD_ATNGW100_MKII)
.vbus_pin = GPIO_PIN_PE(26),
#else
.vbus_pin = -ENODEV,
#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 (IS_ERR(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, 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 mkII uses 32-bit SDRAM interface. Reserve the
* SDRAM-specific pins so that nobody messes with them.
*/
#ifdef CONFIG_BOARD_ATNGW100_MKII
at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
smc_set_timing(&nand_config, &nand_timing);
smc_set_configuration(3, &nand_config);
at32_add_device_nand(0, &atngw100mkii_nand_data);
#endif
at32_add_device_usart(0);
set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
#ifndef CONFIG_BOARD_ATNGW100_MKII_LCD
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
#endif
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, &atngw100_usba_data);
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 (ATNGW100) and PE21 (ATNGW100 mkII) doesn't; it should
* be SMBALERT# (for PMBus), but it's not available off-board.
*/
#ifdef CONFIG_BOARD_ATNGW100_MKII
at32_select_periph(GPIO_PIOE_BASE, 1 << 21, 0, AT32_GPIOF_PULLUP);
#else
at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP);
#endif
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 (ATNGW100) and PE30 (ATNGW100 mkII) 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.
*/
#ifdef CONFIG_BOARD_ATNGW100_MKII
at32_select_gpio(GPIO_PIN_PE(30), 0);
gpio_request(GPIO_PIN_PE(30), "j15");
gpio_direction_input(GPIO_PIN_PE(30));
gpio_export(GPIO_PIN_PE(30), false);
#else
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);
#endif
/* set_irq_type() after the arch_initcall for EIC has run, and
* before the I2C subsystem could try using this IRQ.
*/
return irq_set_irq_type(AT32_EXTINT(3), IRQ_TYPE_EDGE_FALLING);
}
arch_initcall(atngw100_arch_init);
# 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
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
/*
* 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_pdata atstk1000_lcdc_data;
void atstk1000_setup_j2_leds(void);
#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */
/*
* 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 <linux/atmel-mci.h>
#include <video/atmel_lcdc.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>
#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 atmel_nand_data atstk1006_nand_data __initdata = {
.cle = 21,
.ale = 22,
.rdy_pin = GPIO_PIN_PB(30),
.enable_pin = GPIO_PIN_PB(29),
.ecc_mode = NAND_ECC_SOFT,
.parts = nand_partitions,
.num_parts = ARRAY_SIZE(nand_partitions),
};
#endif
struct eth_addr {
u8 addr[6];
};
static struct eth_addr __initdata hw_addr[2];
static struct macb_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 (IS_ERR(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, 0); /* USART 0/B: /dev/ttyS1, IRDA */
#else
at32_map_usart(1, 0, 0); /* USART 1/A: /dev/ttyS0, DB9 */
#endif
/* USART 2/unused: expansion connector */
at32_map_usart(3, 2, 0); /* 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_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
#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, &eth_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, &eth_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);
/*
* 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 <linux/atmel-mci.h>
#include <asm/setup.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, 0); /* USART 0/B: /dev/ttyS1, IRDA */
#else
at32_map_usart(1, 0, 0); /* USART 1/A: /dev/ttyS0, DB9 */
#endif
/* USART 2/unused: expansion connector */
at32_map_usart(3, 2, 0); /* 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_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
#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);
/*
* 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 <linux/atmel-mci.h>
#include <video/atmel_lcdc.h>
#include <asm/setup.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, 0); /* USART 0/B: /dev/ttyS1, IRDA */
#else
at32_map_usart(1, 0, 0); /* USART 1/A: /dev/ttyS0, DB9 */
#endif
/* USART 2/unused: expansion connector */
at32_map_usart(3, 2, 0); /* 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);
/*
* 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);
/*
* 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_pdata __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 */
# 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
/*
* 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);
/*
* 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-mci.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <sound/atmel-abdac.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>
#define PWM_BL_CH 2
/* 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;
static struct atmel_abdac_pdata __initdata abdac0_data = {
};
struct eth_addr {
u8 addr[6];
};
static struct eth_addr __initdata hw_addr[1];
static struct macb_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,
.keep_vref_on = true,
.settle_delay_usecs = 500,
.penirq_recheck_delay_usecs = 100,
};
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 mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = -ENODEV,
.wp_pin = -ENODEV,
},
};
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_pdata __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 (IS_ERR(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 pwm_lookup pwm_lookup[] = {
PWM_LOOKUP("at91sam9rl-pwm", PWM_BL_CH, "pwm-backlight.0", NULL,
5000, PWM_POLARITY_INVERSED),
};
static struct regulator_consumer_supply fixed_power_consumers[] = {
REGULATOR_SUPPLY("power", "pwm-backlight.0"),
};
static struct platform_pwm_backlight_data pwm_bl_data = {
.enable_gpio = GPIO_PIN_PA(28),
.max_brightness = 255,
.dft_brightness = 255,
.lth_brightness = 50,
};
static struct platform_device pwm_bl_device = {
.name = "pwm-backlight",
.dev = {
.platform_data = &pwm_bl_data,
},
};
static void __init favr32_setup_atmel_pwm_bl(void)
{
pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
regulator_register_always_on(0, "fixed", fixed_power_consumers,
ARRAY_SIZE(fixed_power_consumers), 3300000);
platform_device_register(&pwm_bl_device);
at32_select_gpio(pwm_bl_data.enable_gpio, 0);
}
void __init setup_board(void)
{
at32_map_usart(3, 0, 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) {
retval = -EINVAL;
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_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
at32_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */
at32_add_device_usart(0);
set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
spi1_board_info[0].irq = gpio_to_irq(GPIO_PIN_PB(3));
set_abdac_rate(at32_add_device_abdac(0, &abdac0_data));
at32_add_device_pwm(1 << PWM_BL_CH);
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
at32_add_device_mci(0, &mci0_data);
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);
# Hammerhead customization
if BOARD_HAMMERHEAD
config BOARD_HAMMERHEAD_USB
bool "Philips ISP116x-hcd USB support"
help
This enables USB support for Hammerheads internal ISP116x
controller from Philips.
Choose 'Y' here if you want to have your board USB driven.
config BOARD_HAMMERHEAD_LCD
bool "Atmel AT91/AT32 LCD support"
help
This enables LCD support for the Hammerhead board. You may
also add support for framebuffer devices (AT91/AT32 LCD Controller)
and framebuffer console support to get the most out of your LCD.
Choose 'Y' here if you have ordered a Corona daugther board and
want to have support for your Hantronix HDA-351T-LV LCD.
config BOARD_HAMMERHEAD_SND
bool "Atmel AC97 Sound support"
help
This enables Sound support for the Hammerhead board. You may
also go through the ALSA settings to get it working.
Choose 'Y' here if you have ordered a Corona daugther board and
want to make your board funky.
config BOARD_HAMMERHEAD_FPGA
bool "Hammerhead FPGA Support"
default y
help
This adds support for the Cyclone III FPGA from Altera
found on Miromico's Hammerhead board.
Choose 'Y' here if you want to have FPGA support enabled.
You will have to choose the "Hammerhead FPGA Device Support" in
Device Drivers->Misc to be able to use FPGA functionality.
endif # BOARD_ATNGW100
/*
* Hammerhead board-specific flash initialization
*
* Copyright (C) 2008 Miromico AG
*
* 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 <linux/usb/isp116x.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <mach/portmux.h>
#include <mach/at32ap700x.h>
#include <mach/smc.h>
#include "../../mach-at32ap/clock.h"
#include "flash.h"
#define HAMMERHEAD_USB_PERIPH_GCLK0 0x40000000
#define HAMMERHEAD_USB_PERIPH_CS2 0x02000000
#define HAMMERHEAD_USB_PERIPH_EXTINT0 0x02000000
#define HAMMERHEAD_FPGA_PERIPH_MOSI 0x00000002
#define HAMMERHEAD_FPGA_PERIPH_SCK 0x00000020
#define HAMMERHEAD_FPGA_PERIPH_EXTINT3 0x10000000
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, },
};
#ifdef CONFIG_BOARD_HAMMERHEAD_USB
static struct smc_timing isp1160_timing __initdata = {
.ncs_read_setup = 75,
.nrd_setup = 75,
.ncs_write_setup = 75,
.nwe_setup = 75,
/* We use conservative timing settings, as the minimal settings aren't
stable. There may be room for tweaking. */
.ncs_read_pulse = 75, /* min. 33ns */
.nrd_pulse = 75, /* min. 33ns */
.ncs_write_pulse = 75, /* min. 26ns */
.nwe_pulse = 75, /* min. 26ns */
.read_cycle = 225, /* min. 143ns */
.write_cycle = 225, /* min. 136ns */
};
static struct smc_config isp1160_config __initdata = {
.bus_width = 2,
.nrd_controlled = 1,
.nwe_controlled = 1,
.byte_write = 0,
};
/*
* The platform delay function is only used to enforce the strange
* read to write delay. This can not be configured in the SMC. All other
* timings are controlled by the SMC (see timings obove)
* So in isp116x-hcd.c we should comment out USE_PLATFORM_DELAY
*/
void isp116x_delay(struct device *dev, int delay)
{
if (delay > 150)
ndelay(delay - 150);
}
static struct isp116x_platform_data isp1160_data = {
.sel15Kres = 1, /* use internal downstream resistors */
.oc_enable = 0, /* external overcurrent detection */
.int_edge_triggered = 0, /* interrupt is level triggered */
.int_act_high = 0, /* interrupt is active low */
.delay = isp116x_delay, /* platform delay function */
};
static struct resource isp1160_resource[] = {
{
.start = 0x08000000,
.end = 0x08000001,
.flags = IORESOURCE_MEM,
},
{
.start = 0x08000002,
.end = 0x08000003,
.flags = IORESOURCE_MEM,
},
{
.start = 64,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device isp1160_device = {
.name = "isp116x-hcd",
.id = 0,
.resource = isp1160_resource,
.num_resources = 3,
.dev = {
.platform_data = &isp1160_data,
},
};
#endif
#ifdef CONFIG_BOARD_HAMMERHEAD_USB
static int __init hammerhead_usbh_init(void)
{
struct clk *gclk;
struct clk *osc;
int ret;
/* setup smc for usbh */
smc_set_timing(&isp1160_config, &isp1160_timing);
ret = smc_set_configuration(2, &isp1160_config);
if (ret < 0) {
printk(KERN_ERR
"hammerhead: failed to set ISP1160 USBH timing\n");
return ret;
}
/* setup gclk0 to run from osc1 */
gclk = clk_get(NULL, "gclk0");
if (IS_ERR(gclk)) {
ret = PTR_ERR(gclk);
goto err_gclk;
}
osc = clk_get(NULL, "osc1");
if (IS_ERR(osc)) {
ret = PTR_ERR(osc);
goto err_osc;
}
ret = clk_set_parent(gclk, osc);
if (ret < 0) {
pr_debug("hammerhead: failed to set osc1 for USBH clock\n");
goto err_set_clk;
}
/* set clock to 6MHz */
clk_set_rate(gclk, 6000000);
/* and enable */
clk_enable(gclk);
/* select GCLK0 peripheral function */
at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0,
GPIO_PERIPH_A, 0);
/* enable CS2 peripheral function */
at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2,
GPIO_PERIPH_A, 0);
/* H_WAKEUP must be driven low */
at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT);
/* Select EXTINT0 for PB25 */
at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0,
GPIO_PERIPH_A, 0);
/* register usbh device driver */
platform_device_register(&isp1160_device);
err_set_clk:
clk_put(osc);
err_osc:
clk_put(gclk);
err_gclk:
return ret;
}
#endif
#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
static struct smc_timing fpga_timing __initdata = {
.ncs_read_setup = 16,
.nrd_setup = 32,
.ncs_read_pulse = 48,
.nrd_pulse = 32,
.read_cycle = 64,
.ncs_write_setup = 16,
.nwe_setup = 16,
.ncs_write_pulse = 32,
.nwe_pulse = 32,
.write_cycle = 64,
};
static struct smc_config fpga_config __initdata = {
.bus_width = 4,
.nrd_controlled = 1,
.nwe_controlled = 1,
.byte_write = 0,
};
static struct resource hh_fpga0_resource[] = {
{
.start = 0xffe00400,
.end = 0xffe00400 + 0x3ff,
.flags = IORESOURCE_MEM,
},
{
.start = 4,
.end = 4,
.flags = IORESOURCE_IRQ,
},
{
.start = 0x0c000000,
.end = 0x0c000100,
.flags = IORESOURCE_MEM,
},
{
.start = 67,
.end = 67,
.flags = IORESOURCE_IRQ,
},
};
static u64 hh_fpga0_dma_mask = DMA_BIT_MASK(32);
static struct platform_device hh_fpga0_device = {
.name = "hh_fpga",
.id = 0,
.dev = {
.dma_mask = &hh_fpga0_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
.resource = hh_fpga0_resource,
.num_resources = ARRAY_SIZE(hh_fpga0_resource),
};
static struct clk hh_fpga0_spi_clk = {
.name = "spi_clk",
.dev = &hh_fpga0_device.dev,
.mode = pba_clk_mode,
.get_rate = pba_clk_get_rate,
.index = 1,
};
struct platform_device *__init at32_add_device_hh_fpga(void)
{
/* Select peripheral functionallity for SPI SCK and MOSI */
at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK,
GPIO_PERIPH_B, 0);
at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI,
GPIO_PERIPH_B, 0);
/* reserve all other needed gpio
* We have on board pull ups, so there is no need
* to enable gpio pull ups */
/* INIT_DONE (input) */
at32_select_gpio(GPIO_PIN_PB(0), 0);
/* nSTATUS (input) */
at32_select_gpio(GPIO_PIN_PB(2), 0);
/* nCONFIG (output, low) */
at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT);
/* CONF_DONE (input) */
at32_select_gpio(GPIO_PIN_PB(4), 0);
/* Select EXTINT3 for PB28 (Interrupt from FPGA) */
at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3,
GPIO_PERIPH_A, 0);
/* Get our parent clock */
hh_fpga0_spi_clk.parent = clk_get(NULL, "pba");
clk_put(hh_fpga0_spi_clk.parent);
/* Register clock in at32 clock tree */
at32_clk_register(&hh_fpga0_spi_clk);
platform_device_register(&hh_fpga0_device);
return &hh_fpga0_device;
}
#endif
/* This needs to be called after the SMC has been initialized */
static int __init hammerhead_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 "hammerhead: failed to set NOR flash timing\n");
return ret;
}
platform_device_register(&flash_device);
#ifdef CONFIG_BOARD_HAMMERHEAD_USB
hammerhead_usbh_init();
#endif
#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
/* Setup SMC for FPGA interface */
smc_set_timing(&fpga_config, &fpga_timing);
ret = smc_set_configuration(3, &fpga_config);
#endif
if (ret < 0) {
printk(KERN_ERR "hammerhead: failed to set FPGA timing\n");
return ret;
}
return 0;
}
device_initcall(hammerhead_flash_init);
#ifndef __BOARDS_HAMMERHEAD_FLASH_H
#define __BOARDS_HAMMERHEAD_FLASH_H
struct platform_device *at32_add_device_hh_fpga(void);
#endif /* __BOARDS_HAMMERHEAD_FLASH_H */
/*
* Board-specific setup code for the Miromico Hammerhead board
*
* Copyright (C) 2008 Miromico AG
*
* 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/atmel-mci.h>
#include <linux/clk.h>
#include <linux/fb.h>
#include <linux/etherdevice.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/spi/spi.h>
#include <video/atmel_lcdc.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>
#include <sound/atmel-ac97c.h>
#include "../../mach-at32ap/clock.h"
#include "flash.h"
/* Oscillator frequencies. These are board-specific */
unsigned long at32_board_osc_rates[3] = {
[0] = 32768, /* 32.768 kHz on RTC osc */
[1] = 25000000, /* 25MHz on osc0 */
[2] = 12000000, /* 12 MHz on osc1 */
};
/* Initialized by bootloader-specific startup code. */
struct tag *bootloader_tags __initdata;
#ifdef CONFIG_BOARD_HAMMERHEAD_LCD
static struct fb_videomode __initdata hda350tlv_modes[] = {
{
.name = "320x240 @ 75",
.refresh = 75,
.xres = 320,
.yres = 240,
.pixclock = KHZ2PICOS(6891),
.left_margin = 48,
.right_margin = 18,
.upper_margin = 18,
.lower_margin = 4,
.hsync_len = 20,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
};
static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = {
.manufacturer = "HAN",
.monitor = "HDA350T-LV",
.modedb = hda350tlv_modes,
.modedb_len = ARRAY_SIZE(hda350tlv_modes),
.hfmin = 14900,
.hfmax = 22350,
.vfmin = 60,
.vfmax = 90,
.dclkmax = 10000000,
};
struct atmel_lcdfb_pdata __initdata hammerhead_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 = &hammerhead_hda350t_monspecs,
.guard_time = 2,
};
#endif
static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = -ENODEV,
.wp_pin = -ENODEV,
},
};
struct eth_addr {
u8 addr[6];
};
static struct eth_addr __initdata hw_addr[1];
static struct macb_platform_data __initdata eth_data[1];
/*
* 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 = 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 (IS_ERR(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, 0); /* USART 1: /dev/ttyS0, DB9 */
at32_setup_serial_console(0);
}
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[] = {};
#ifdef CONFIG_BOARD_HAMMERHEAD_SND
static struct ac97c_platform_data ac97c_data = {
.reset_pin = GPIO_PIN_PA(16),
};
#endif
static int __init hammerhead_init(void)
{
/*
* Hammerhead uses 32-bit SDRAM interface. Reserve the
* SDRAM-specific pins so that nobody messes with them.
*/
at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
at32_add_device_usart(0);
/* Reserve PB29 (GCLK3). This pin is used as clock source
* for ETH PHY (25MHz). GCLK3 setup is done by U-Boot.
*/
at32_reserve_pin(GPIO_PIOB_BASE, (1<<29));
/*
* Hammerhead uses only one ethernet port, so we don't set
* address of second port
*/
set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
at32_add_device_hh_fpga();
#endif
at32_add_device_mci(0, &mci0_data);
#ifdef CONFIG_BOARD_HAMMERHEAD_USB
at32_add_device_usba(0, NULL);
#endif
#ifdef CONFIG_BOARD_HAMMERHEAD_LCD
at32_add_device_lcdc(0, &hammerhead_lcdc_data, fbmem_start,
fbmem_size, ATMEL_LCDC_PRI_24BIT);
#endif
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));
#ifdef CONFIG_BOARD_HAMMERHEAD_SND
at32_add_device_ac97c(0, &ac97c_data, AC97C_BOTH);
#endif
/* Select the Touchscreen interrupt pin mode */
at32_select_periph(GPIO_PIOB_BASE, 0x08000000, GPIO_PERIPH_A, 0);
return 0;
}
postcore_initcall(hammerhead_init);
# Merisc customization
if BOARD_MERISC
endif # BOARD_MERISC
obj-y += setup.o flash.o display.o merisc_sysfs.o
/*
* Display setup code for the Merisc board
*
* Copyright (C) 2008 Martinsson Elektronik AB
*
* 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/fb.h>
#include <video/atmel_lcdc.h>
#include <asm/setup.h>
#include <mach/board.h>
#include "merisc.h"
static struct fb_videomode merisc_fb_videomode[] = {
{
.refresh = 44,
.xres = 640,
.yres = 480,
.left_margin = 96,
.right_margin = 96,
.upper_margin = 34,
.lower_margin = 8,
.hsync_len = 64,
.vsync_len = 64,
.name = "640x480 @ 44",
.pixclock = KHZ2PICOS(25180),
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
};
static struct fb_monspecs merisc_fb_monspecs = {
.manufacturer = "Kyo",
.monitor = "TCG075VG2AD",
.modedb = merisc_fb_videomode,
.modedb_len = ARRAY_SIZE(merisc_fb_videomode),
.hfmin = 30000,
.hfmax = 33333,
.vfmin = 60,
.vfmax = 90,
.dclkmax = 30000000,
};
struct atmel_lcdfb_pdata merisc_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
| ATMEL_LCDC_MEMOR_BIG),
.default_monspecs = &merisc_fb_monspecs,
.guard_time = 2,
};
static int __init merisc_display_init(void)
{
at32_add_device_lcdc(0, &merisc_lcdc_data, fbmem_start,
fbmem_size, 0);
return 0;
}
device_initcall(merisc_display_init);
/*
* Merisc board-specific flash initialization
*
* Copyright (C) 2008 Martinsson Elektronik AB
*
* 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>
/* Will be translated to units of 14.3 ns, rounded up */
static struct smc_timing flash_timing __initdata = {
.ncs_read_setup = 1 * 14,
.nrd_setup = 5 * 14,
.ncs_write_setup = 1 * 14,
.nwe_setup = 2 * 14,
.ncs_read_pulse = 12 * 14,
.nrd_pulse = 7 * 14,
.ncs_write_pulse = 8 * 14,
.nwe_pulse = 4 * 14,
.read_cycle = 14 * 14,
.write_cycle = 10 * 14,
};
static struct smc_config flash_config __initdata = {
.bus_width = 2,
.nrd_controlled = 1,
.nwe_controlled = 1,
.byte_write = 1,
.tdf_cycles = 3,
};
static struct mtd_partition flash_0_parts[] = {
{
.name = "boot",
.offset = 0x00000000,
.size = 0x00060000,
.mask_flags = 0,
},
{
.name = "kernel",
.offset = 0x00060000,
.size = 0x00200000,
.mask_flags = 0,
},
{
.name = "root",
.offset = 0x00260000,
.size = MTDPART_SIZ_FULL,
.mask_flags = 0,
},
};
static struct mtd_partition flash_1_parts[] = {
{
.name = "2ndflash",
.offset = 0x00000000,
.size = MTDPART_SIZ_FULL,
.mask_flags = 0,
},
};
static struct physmap_flash_data flash_data[] = {
{
.width = 2,
.nr_parts = ARRAY_SIZE(flash_0_parts),
.parts = flash_0_parts,
},
{
.width = 2,
.nr_parts = ARRAY_SIZE(flash_1_parts),
.parts = flash_1_parts,
}
};
static struct resource flash_resource[] = {
{
.start = 0x00000000,
.end = 0x03ffffff,
.flags = IORESOURCE_MEM,
},
{
.start = 0x04000000,
.end = 0x07ffffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device flash_device[] = {
{
.name = "physmap-flash",
.id = 0,
.resource = &flash_resource[0],
.num_resources = 1,
.dev = {
.platform_data = &flash_data[0],
},
},
{
.name = "physmap-flash",
.id = 1,
.resource = &flash_resource[1],
.num_resources = 1,
.dev = {
.platform_data = &flash_data[1],
},
},
};
static int __init merisc_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 "Merisc: failed to set NOR flash timing #0\n");
return ret;
}
ret = smc_set_configuration(4, &flash_config);
if (ret < 0) {
printk(KERN_ERR "Merisc: failed to set NOR flash timing #1\n");
return ret;
}
platform_device_register(&flash_device[0]);
platform_device_register(&flash_device[1]);
return 0;
}
device_initcall(merisc_flash_init);
/*
* Merisc exports
*
* Copyright (C) 2008 Martinsson Elektronik AB
*
* 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_MERISC_MERISC_H
#define __ARCH_AVR32_BOARDS_MERISC_MERISC_H
const char *merisc_revision(void);
const char *merisc_model(void);
extern struct class merisc_class;
#endif /* __ARCH_AVR32_BOARDS_MERISC_MERISC_H */
/*
* Merisc sysfs exports
*
* Copyright (C) 2008 Martinsson Elektronik AB
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/timer.h>
#include <linux/err.h>
#include <linux/ctype.h>
#include "merisc.h"
static ssize_t merisc_model_show(struct class *class, char *buf)
{
ssize_t ret = 0;
sprintf(buf, "%s\n", merisc_model());
ret = strlen(buf) + 1;
return ret;
}
static ssize_t merisc_revision_show(struct class *class, char *buf)
{
ssize_t ret = 0;
sprintf(buf, "%s\n", merisc_revision());
ret = strlen(buf) + 1;
return ret;
}
static struct class_attribute merisc_class_attrs[] = {
__ATTR(model, S_IRUGO, merisc_model_show, NULL),
__ATTR(revision, S_IRUGO, merisc_revision_show, NULL),
__ATTR_NULL,
};
struct class merisc_class = {
.name = "merisc",
.owner = THIS_MODULE,
.class_attrs = merisc_class_attrs,
};
static int __init merisc_sysfs_init(void)
{
int status;
status = class_register(&merisc_class);
if (status < 0)
return status;
return 0;
}
postcore_initcall(merisc_sysfs_init);
/*
* Board-specific setup code for the Merisc
*
* Copyright (C) 2008 Martinsson Elektronik AB
*
* 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/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/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/ads7846.h>
#include <linux/irq.h>
#include <linux/fb.h>
#include <linux/atmel-mci.h>
#include <linux/pwm.h>
#include <linux/leds_pwm.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>
#include "merisc.h"
/* Holds the autodetected board model and revision */
static int merisc_board_id;
/* Initialized by bootloader-specific startup code. */
struct tag *bootloader_tags __initdata;
/* 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 */
};
struct eth_addr {
u8 addr[6];
};
static struct eth_addr __initdata hw_addr[2];
static struct macb_platform_data __initdata eth_data[2];
static int ads7846_get_pendown_state_PB26(void)
{
return !gpio_get_value(GPIO_PIN_PB(26));
}
static int ads7846_get_pendown_state_PB28(void)
{
return !gpio_get_value(GPIO_PIN_PB(28));
}
static struct ads7846_platform_data __initdata ads7846_data = {
.model = 7846,
.vref_delay_usecs = 100,
.vref_mv = 0,
.keep_vref_on = 0,
.settle_delay_usecs = 150,
.penirq_recheck_delay_usecs = 1,
.x_plate_ohms = 800,
.debounce_rep = 4,
.debounce_max = 10,
.debounce_tol = 50,
.get_pendown_state = ads7846_get_pendown_state_PB26,
.filter_init = NULL,
.filter = NULL,
.filter_cleanup = NULL,
};
static struct spi_board_info __initdata spi0_board_info[] = {
{
.modalias = "ads7846",
.max_speed_hz = 3250000,
.chip_select = 0,
.bus_num = 0,
.platform_data = &ads7846_data,
.mode = SPI_MODE_0,
},
};
static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = GPIO_PIN_PE(19),
.wp_pin = GPIO_PIN_PE(20),
.detect_is_active_high = true,
},
};
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;
regs = (void __iomem __force *)res->start;
pclk = clk_get(&pdev->dev, "pclk");
if (IS_ERR(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);
}
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,
};
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[] = {
{
I2C_BOARD_INFO("pcf8563", 0x51)
},
};
#if IS_ENABLED(CONFIG_LEDS_PWM)
static struct pwm_lookup pwm_lookup[] = {
PWM_LOOKUP("at91sam9rl-pwm", 0, "leds_pwm", "backlight",
5000, PWM_POLARITY_NORMAL),
};
static struct led_pwm pwm_leds[] = {
{
.name = "backlight",
.max_brightness = 255,
},
};
static struct led_pwm_platform_data pwm_data = {
.num_leds = ARRAY_SIZE(pwm_leds),
.leds = pwm_leds,
};
static struct platform_device leds_pwm = {
.name = "leds_pwm",
.id = -1,
.dev = {
.platform_data = &pwm_data,
},
};
#endif
const char *merisc_model(void)
{
switch (merisc_board_id) {
case 0:
case 1:
return "500-01";
case 2:
return "BT";
default:
return "Unknown";
}
}
const char *merisc_revision(void)
{
switch (merisc_board_id) {
case 0:
return "B";
case 1:
return "D";
case 2:
return "A";
default:
return "Unknown";
}
}
static void detect_merisc_board_id(void)
{
/* Board ID pins MUST be set as input or the board may be damaged */
at32_select_gpio(GPIO_PIN_PA(24), AT32_GPIOF_PULLUP);
at32_select_gpio(GPIO_PIN_PA(25), AT32_GPIOF_PULLUP);
at32_select_gpio(GPIO_PIN_PA(26), AT32_GPIOF_PULLUP);
at32_select_gpio(GPIO_PIN_PA(27), AT32_GPIOF_PULLUP);
merisc_board_id = !gpio_get_value(GPIO_PIN_PA(24)) +
!gpio_get_value(GPIO_PIN_PA(25)) * 2 +
!gpio_get_value(GPIO_PIN_PA(26)) * 4 +
!gpio_get_value(GPIO_PIN_PA(27)) * 8;
}
void __init setup_board(void)
{
at32_map_usart(0, 0, 0);
at32_map_usart(1, 1, 0);
at32_map_usart(3, 3, 0);
at32_setup_serial_console(1);
}
static int __init merisc_init(void)
{
detect_merisc_board_id();
printk(KERN_NOTICE "BOARD: Merisc %s revision %s\n", merisc_model(),
merisc_revision());
/* Reserve pins for SDRAM */
at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL | (1 << 26));
if (merisc_board_id >= 1)
at32_map_usart(2, 2, 0);
at32_add_device_usart(0);
at32_add_device_usart(1);
if (merisc_board_id >= 1)
at32_add_device_usart(2);
at32_add_device_usart(3);
set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
/* ADS7846 PENIRQ */
if (merisc_board_id == 0) {
ads7846_data.get_pendown_state = ads7846_get_pendown_state_PB26;
at32_select_periph(GPIO_PIOB_BASE, 1 << 26,
GPIO_PERIPH_A, AT32_GPIOF_PULLUP);
spi0_board_info[0].irq = AT32_EXTINT(1);
} else {
ads7846_data.get_pendown_state = ads7846_get_pendown_state_PB28;
at32_select_periph(GPIO_PIOB_BASE, 1 << 28, GPIO_PERIPH_A,
AT32_GPIOF_PULLUP);
spi0_board_info[0].irq = AT32_EXTINT(3);
}
/* ADS7846 busy pin */
at32_select_gpio(GPIO_PIN_PA(4), AT32_GPIOF_PULLUP);
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
at32_add_device_mci(0, &mci0_data);
#if IS_ENABLED(CONFIG_LEDS_PWM)
pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
at32_add_device_pwm((1 << 0) | (1 << 2));
platform_device_register(&leds_pwm);
#else
at32_add_device_pwm((1 << 2));
#endif
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(merisc_init);
/*
* 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);
/*
* 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_pdata 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 <linux/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 pt0434827_modes[] = {
{
.name = "480x272 @ 72",
.refresh = 72,
.xres = 480, .yres = 272,
.pixclock = KHZ2PICOS(10000),
.left_margin = 1, .right_margin = 1,
.upper_margin = 12, .lower_margin = 1,
.hsync_len = 42, .vsync_len = 1,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
};
static struct fb_monspecs __initdata mimc200_default_monspecs = {
.manufacturer = "PT",
.monitor = "PT0434827-A401",
.modedb = pt0434827_modes,
.modedb_len = ARRAY_SIZE(pt0434827_modes),
.hfmin = 14820,
.hfmax = 22230,
.vfmin = 60,
.vfmax = 85,
.dclkmax = 25200000,
};
struct atmel_lcdfb_pdata __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 macb_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 (IS_ERR(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, 0); /* USART 0: /dev/ttyS0 (TTL --> Altera) */
at32_map_usart(1, 1, 0); /* USART 1: /dev/ttyS1 (RS232) */
at32_map_usart(2, 2, 0); /* USART 2: /dev/ttyS2 (RS485) */
at32_map_usart(3, 3, 0); /* 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_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, &eth_data[0]));
set_hw_addr(at32_add_device_eth(1, &eth_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,
ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_CONTROL | ATMEL_LCDC_ALT_24B_DATA);
return 0;
}
postcore_initcall(mimc200_init);
uImage
uImage.srec
vmlinux.cso
sfdwarf.log
#
# Copyright (C) 2004-2006 Atmel Corporation
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
extra-y := vmlinux.bin vmlinux.gz
OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note.gnu.build-id
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,gzip)
UIMAGE_LOADADDR = $(CONFIG_LOAD_ADDRESS)
UIMAGE_ENTRYADDR = $(CONFIG_ENTRY_ADDRESS)
UIMAGE_COMPRESSION = gzip
targets += uImage uImage.srec
$(obj)/uImage: $(obj)/vmlinux.gz
$(call if_changed,uimage)
@echo ' Image $@ is ready'
OBJCOPYFLAGS_uImage.srec := -I binary -O srec
$(obj)/uImage.srec: $(obj)/uImage
$(call if_changed,objcopy)
OBJCOPYFLAGS_vmlinux.elf := --change-section-lma .text-0x80000000 \
--change-section-lma __ex_table-0x80000000 \
--change-section-lma .rodata-0x80000000 \
--change-section-lma .data-0x80000000 \
--change-section-lma .init-0x80000000 \
--change-section-lma .bss-0x80000000 \
--change-section-lma __param-0x80000000 \
--change-section-lma __ksymtab-0x80000000 \
--change-section-lma __ksymtab_gpl-0x80000000 \
--change-section-lma __kcrctab-0x80000000 \
--change-section-lma __kcrctab_gpl-0x80000000 \
--change-section-lma __ksymtab_strings-0x80000000 \
--set-start 0xa0000000
$(obj)/vmlinux.elf: vmlinux FORCE
$(call if_changed,objcopy)
quiet_cmd_sfdwarf = SFDWARF $@
cmd_sfdwarf = sfdwarf $< TO $@ GNUAVR IW $(SFDWARF_FLAGS) > $(obj)/sfdwarf.log
$(obj)/vmlinux.cso: $(obj)/vmlinux.elf FORCE
$(call if_changed,sfdwarf)
install: $(BOOTIMAGE)
sh $(srctree)/install-kernel.sh $<
# Generated files to be removed upon make clean
clean-files := vmlinux.elf vmlinux.bin vmlinux.gz uImage uImage.srec
extra-y := head.o
obj-y := empty.o
/*
* Startup code for use with the u-boot bootloader.
*
* Copyright (C) 2004-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 <asm/setup.h>
#include <asm/thread_info.h>
#include <asm/sysreg.h>
/*
* The kernel is loaded where we want it to be and all caches
* have just been flushed. We get two parameters from u-boot:
*
* r12 contains a magic number (ATAG_MAGIC)
* r11 points to a tag table providing information about
* the system.
*/
.section .init.text,"ax"
.global _start
_start:
/* Initialize .bss */
lddpc r2, bss_start_addr
lddpc r3, end_addr
mov r0, 0
mov r1, 0
1: st.d r2++, r0
cp r2, r3
brlo 1b
/* Initialize status register */
lddpc r0, init_sr
mtsr SYSREG_SR, r0
/* Set initial stack pointer */
lddpc sp, stack_addr
sub sp, -THREAD_SIZE
#ifdef CONFIG_FRAME_POINTER
/* Mark last stack frame */
mov lr, 0
mov r7, 0
#endif
/* Check if the boot loader actually provided a tag table */
lddpc r0, magic_number
cp.w r12, r0
brne no_tag_table
/*
* Save the tag table address for later use. This must be done
* _after_ .bss has been initialized...
*/
lddpc r0, tag_table_addr
st.w r0[0], r11
/* Jump to loader-independent setup code */
rjmp kernel_entry
.align 2
magic_number:
.long ATAG_MAGIC
tag_table_addr:
.long bootloader_tags
bss_start_addr:
.long __bss_start
end_addr:
.long _end
init_sr:
.long 0x007f0000 /* Supervisor mode, everything masked */
stack_addr:
.long init_thread_union
panic_addr:
.long panic
no_tag_table:
sub r12, pc, (. - 2f)
/* branch to panic() which can be far away with that construct */
lddpc pc, panic_addr
2: .asciz "Boot loader didn't provide correct magic number\n"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_BASE_FULL is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_BOARD_ATNGW100_MKI=y
# CONFIG_OWNERSHIP_TRACE is not set
CONFIG_NMI_DEBUGGING=y
CONFIG_CPU_FREQ=y
# CONFIG_CPU_FREQ_STAT is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_AVR32_AT32AP_CPUFREQ=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_ADVANCED is not set
CONFIG_NETFILTER_XTABLES=y
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_ATMEL_TCLIB=y
CONFIG_NETDEVICES=y
CONFIG_TUN=m
CONFIG_MACB=y
CONFIG_PPP=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_DEFLATE=m
CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
CONFIG_PPP_ASYNC=m
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_ATMEL=y
CONFIG_SERIAL_ATMEL_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=m
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_GPIO=m
CONFIG_SPI=y
CONFIG_SPI_ATMEL=y
CONFIG_SPI_SPIDEV=m
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_AT32AP700X_WDT=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y
CONFIG_MMC_TEST=m
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT32AP700X=y
CONFIG_DMADEVICES=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
CONFIG_EXT4_FS=y
# CONFIG_DNOTIFY is not set
CONFIG_FUSE_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=850
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_CONFIGFS_FS=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
CONFIG_CIFS=m
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_850=m
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
CONFIG_DEBUG_FS=y
CONFIG_FRAME_POINTER=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DETECT_HUNG_TASK=y
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
#include <generated/asm-offsets.h>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册