From 638f634c3b016e3a200433ef1ca7127a5543e799 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 22 Mar 2013 11:17:40 +0100 Subject: platform-energymicro-efm32gg-dk3750: move to Linux 3.9-rc1 --- kernelconfig-3.9-rc1 | 1217 ++++++++++++++++++++ ...01-irqchip-Add-support-for-ARMv7-M-s-NVIC.patch | 231 ++++ .../0002-ARM-Add-base-support-for-ARMv7-M.patch | 770 +++++++++++++ ...RMv7-M-Add-support-for-exception-handling.patch | 347 ++++++ ...7-M-Allow-the-building-of-new-kernel-port.patch | 170 +++ .../0005-hwmon-efm32-adc-new-driver.patch | 358 ++++++ ...-spi-new-controller-driver-for-efm32-SoCs.patch | 509 ++++++++ ...tform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch | 773 +++++++++++++ .../0008-ARM-efm32-some-more-stuff.patch | 296 +++++ ...-driver-for-Energy-Micro-s-GPIO-component.patch | 387 +++++++ .../0010-efm-board-controller-driver.patch | 235 ++++ .../0011-ARM-v7m-add-trivial-suspend-support.patch | 96 ++ ...012-ARM-efm32-add-trivial-suspend-support.patch | 75 ++ ...low-a-bootloader-to-be-embedded-and-do-it.patch | 307 +++++ ...reserve-memory-for-device-tree-if-it-s-be.patch | 32 + ...tack-dumps-provoked-by-BUG-a-bit-more-hel.patch | 37 + .../0016-HACK-ARM-increase-TASK_SIZE-for-MMU.patch | 35 + .../0017-HACK-work-around-for-big-images.patch | 21 + patches/linux-3.9-rc1/0018-wip.patch | 22 + .../linux-3.9-rc1/rmk-devel-stable-20130309.patch | 412 +++++++ patches/linux-3.9-rc1/series | 19 + platformconfig | 4 +- 22 files changed, 6351 insertions(+), 2 deletions(-) create mode 100644 kernelconfig-3.9-rc1 create mode 100644 patches/linux-3.9-rc1/0001-irqchip-Add-support-for-ARMv7-M-s-NVIC.patch create mode 100644 patches/linux-3.9-rc1/0002-ARM-Add-base-support-for-ARMv7-M.patch create mode 100644 patches/linux-3.9-rc1/0003-ARM-ARMv7-M-Add-support-for-exception-handling.patch create mode 100644 patches/linux-3.9-rc1/0004-ARM-ARMv7-M-Allow-the-building-of-new-kernel-port.patch create mode 100644 patches/linux-3.9-rc1/0005-hwmon-efm32-adc-new-driver.patch create mode 100644 patches/linux-3.9-rc1/0006-spi-new-controller-driver-for-efm32-SoCs.patch create mode 100644 patches/linux-3.9-rc1/0007-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch create mode 100644 patches/linux-3.9-rc1/0008-ARM-efm32-some-more-stuff.patch create mode 100644 patches/linux-3.9-rc1/0009-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch create mode 100644 patches/linux-3.9-rc1/0010-efm-board-controller-driver.patch create mode 100644 patches/linux-3.9-rc1/0011-ARM-v7m-add-trivial-suspend-support.patch create mode 100644 patches/linux-3.9-rc1/0012-ARM-efm32-add-trivial-suspend-support.patch create mode 100644 patches/linux-3.9-rc1/0013-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch create mode 100644 patches/linux-3.9-rc1/0014-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch create mode 100644 patches/linux-3.9-rc1/0015-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch create mode 100644 patches/linux-3.9-rc1/0016-HACK-ARM-increase-TASK_SIZE-for-MMU.patch create mode 100644 patches/linux-3.9-rc1/0017-HACK-work-around-for-big-images.patch create mode 100644 patches/linux-3.9-rc1/0018-wip.patch create mode 100644 patches/linux-3.9-rc1/rmk-devel-stable-20130309.patch create mode 100644 patches/linux-3.9-rc1/series diff --git a/kernelconfig-3.9-rc1 b/kernelconfig-3.9-rc1 new file mode 100644 index 0000000..3801f0a --- /dev/null +++ b/kernelconfig-3.9-rc1 @@ -0,0 +1,1217 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.9.0-rc1 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_NO_IOPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0x00000000 +CONFIG_PHYS_OFFSET=0x88000000 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_FHANDLE is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_ALWAYS_USE_PERSISTENT_CLOCK is not set +CONFIG_KTIME_SCALAR=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +# CONFIG_TINY_PREEMPT_RCU is not set +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_NOCB_CPU is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=12 +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +CONFIG_UIDGID_CONVERTED=y +# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_HAVE_UID16=y +# CONFIG_UID16 is not set +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_BASE_FULL is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +# CONFIG_SIGNALFD is not set +CONFIG_TIMERFD=y +# CONFIG_EVENTFD is not set +# CONFIG_AIO is not set +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_MMAP_ALLOW_UNINITIALIZED is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_VIRT_TO_BUS=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_BASE_SMALL=1 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_FREEZER=y + +# +# System Type +# +# CONFIG_MMU is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_EBSA110 is not set +CONFIG_ARCH_EFM32=y +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_DAVINCI is not set + +# +# Processor Type +# +# CONFIG_CPU_ARM7TDMI is not set +# CONFIG_CPU_ARM9TDMI is not set +CONFIG_CPU_V7M=y +CONFIG_CPU_THUMBONLY=y +CONFIG_CPU_32v7M=y +CONFIG_CPU_ABRT_NOMMU=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_NOP=y +CONFIG_CPU_CACHE_VIPT=y + +# +# Processor Features +# +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_NR_BANKS=8 +CONFIG_SET_MEM_PARAM=y +CONFIG_DRAM_BASE=0x88000000 +CONFIG_DRAM_SIZE=0x00400000 +CONFIG_FLASH_MEM_BASE=0x8c000000 +CONFIG_FLASH_SIZE=0x01000000 + +# +# Bus support +# +CONFIG_ARCH_NO_VIRT_TO_BUS=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +CONFIG_THUMB2_KERNEL=y +CONFIG_ARM_ASM_UNIFIED=y +CONFIG_AEABI=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=9 +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="" +CONFIG_XIP_KERNEL=y +CONFIG_XIP_PHYS_ADDR=0x8c000000 +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# + +# +# Userspace binary formats +# +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_FLAT=y +# CONFIG_BINFMT_ZFLAT is not set +CONFIG_BINFMT_SHARED_FLAT=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_COREDUMP is not set + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +CONFIG_HAVE_NET_DSA=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +# CONFIG_DMA_SHARED_BUFFER is not set + +# +# Bus devices +# +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PHYSMAP_OF is not set +CONFIG_MTD_UCLINUX=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_PROC_DEVICETREE is not set +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_NET=y +CONFIG_OF_MTD=y +# CONFIG_PARPORT is not set +# CONFIG_BLK_DEV is not set + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_ATMEL_SSC is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT25 is not set +CONFIG_EEPROM_93CX6=y +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_MII=y +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +CONFIG_ETHERNET=y +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +CONFIG_NET_VENDOR_MICREL=y +CONFIG_KS8851=y +# CONFIG_KS8851_MLL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_PHYLIB is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_N_HDLC is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_SERIAL_EFM32_UART=y +CONFIG_SERIAL_EFM32_UART_CONSOLE=y +# CONFIG_SERIAL_ARC is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +CONFIG_SPI_EFM32=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +# CONFIG_PTP_1588_CLOCK is not set + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +# CONFIG_PTP_1588_CLOCK_PCH is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_EFM32=y +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_TS5500 is not set + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_ADCXX is not set +CONFIG_SENSORS_EFM32_ADC=y +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_SYSCON is not set +CONFIG_MFD_EFM32BOARD=y +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_OF_DISPLAY_TIMING is not set +# CONFIG_OF_VIDEOMODE is not set +# CONFIG_FB is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB_ARCH_HAS_XHCI is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_STAGING is not set + +# +# Hardware Spinlock drivers +# +CONFIG_CLKSRC_MMIO=y +# CONFIG_MAILBOX is not set +# CONFIG_IOMMU_SUPPORT is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_NVIC=y +# CONFIG_IPACK_BUS is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_FILE_LOCKING is not set +# CONFIG_FSNOTIFY is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_ROMFS_BACKED_BY_BLOCK is not set +CONFIG_ROMFS_BACKED_BY_MTD=y +# CONFIG_ROMFS_BACKED_BY_BOTH is not set +CONFIG_ROMFS_ON_MTD=y +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_NOMMU_REGIONS is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU_DELAY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_EFM32_USART1 is not set +CONFIG_DEBUG_EFM32_UART1=y +# CONFIG_DEBUG_LL_UART_NONE is not set +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_SEMIHOSTING is not set +CONFIG_DEBUG_IMX_UART_PORT=1 +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_EARLY_PRINTK is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +# CONFIG_VIRTUALIZATION is not set diff --git a/patches/linux-3.9-rc1/0001-irqchip-Add-support-for-ARMv7-M-s-NVIC.patch b/patches/linux-3.9-rc1/0001-irqchip-Add-support-for-ARMv7-M-s-NVIC.patch new file mode 100644 index 0000000..f73158a --- /dev/null +++ b/patches/linux-3.9-rc1/0001-irqchip-Add-support-for-ARMv7-M-s-NVIC.patch @@ -0,0 +1,231 @@ +From 35aa7416d459f7d8a84a3aa93955dd5c21594655 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Fri, 21 May 2010 18:06:43 +0100 +Subject: [PATCH 01/18] irqchip: Add support for ARMv7-M's NVIC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This interrupt controller is found on Cortex-M3 and Cortex-M4 machines. + +Support for this controller appeared in Catalin's Cortex tree based on +2.6.33 but was nearly completely rewritten. + +Signed-off-by: Catalin Marinas +Signed-off-by: Uwe Kleine-König +Forwarded: id:1363612826-15623-1-git-send-email-u.kleine-koenig@pengutronix.de (v2) +--- + drivers/irqchip/Kconfig | 4 ++ + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-nvic.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 181 insertions(+) + create mode 100644 drivers/irqchip/irq-nvic.c + +diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig +index a350969..18657fd 100644 +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -10,6 +10,10 @@ config ARM_GIC + config GIC_NON_BANKED + bool + ++config ARM_NVIC ++ bool ++ select IRQ_DOMAIN ++ + config ARM_VIC + bool + select IRQ_DOMAIN +diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile +index 98e3b87..7227c5f 100644 +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -7,5 +7,6 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o + obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o + obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o + obj-$(CONFIG_ARM_GIC) += irq-gic.o ++obj-$(CONFIG_ARM_NVIC) += irq-nvic.o + obj-$(CONFIG_ARM_VIC) += irq-vic.o + obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o +diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c +new file mode 100644 +index 0000000..721c328 +--- /dev/null ++++ b/drivers/irqchip/irq-nvic.c +@@ -0,0 +1,176 @@ ++/* ++ * drivers/irq/irq-nvic.c ++ * ++ * Copyright (C) 2008 ARM Limited, All Rights Reserved. ++ * Copyright (C) 2013 Pengutronix ++ * ++ * 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. ++ * ++ * Support for the Nested Vectored Interrupt Controller found on the ++ * ARMv7-M CPUs (Cortex-M3/M4) ++ */ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "irqchip.h" ++ ++#define NVIC_ISER 0x000 ++#define NVIC_ICER 0x080 ++#define NVIC_IPR 0x300 ++ ++/* ++ * Each bank handles 32 irqs. Only the 16th (= last) bank handles only ++ * 16 irqs yielding a maximum of 15 * 32 + 16 = 496 interrupts. ++ */ ++#define NVIC_MAX_IRQ 496 ++ ++struct nvic_bank_data { ++ /* ++ * For irq i base holds nvic_base + 4 * i / 32. So you can access the ++ * right ISER register (i.e ISER[i / 32]) by just taking base + ISER. ++ * Ditto for ICER. ++ */ ++ void __iomem *base; ++}; ++ ++static inline void __iomem *nvic_bank_base(struct irq_data *d) ++{ ++ struct nvic_bank_data *data = irq_data_get_irq_chip_data(d); ++ return data->base; ++} ++ ++static void nvic_mask_irq(struct irq_data *d) ++{ ++ u32 mask = 1 << (d->hwirq % 32); ++ ++ writel_relaxed(mask, nvic_bank_base(d) + NVIC_ICER); ++} ++ ++static void nvic_unmask_irq(struct irq_data *d) ++{ ++ u32 mask = 1 << (d->hwirq % 32); ++ ++ writel_relaxed(mask, nvic_bank_base(d) + NVIC_ISER); ++} ++ ++static void nvic_eoi(struct irq_data *d) ++{ ++ /* ++ * This is a no-op as end of interrupt is signaled by the exception ++ * return sequence. ++ */ ++} ++ ++static struct irq_chip nvic_chip = { ++ .name = "NVIC", ++ .irq_mask = nvic_mask_irq, ++ .irq_unmask = nvic_unmask_irq, ++ .irq_eoi = nvic_eoi, ++}; ++ ++static int __init nvic_init_bases(struct device_node *node, ++ void __iomem *nvic_base) ++{ ++ unsigned int irqs, i; ++ int irq_base, ret = -ENOMEM; ++ struct irq_domain *irq_domain; ++ struct nvic_bank_data *bank_data; ++ unsigned numbanks = (readl_relaxed(V7M_SCS_ICTR) & ++ V7M_SCS_ICTR_INTLINESNUM_MASK) + 1; ++ ++ irqs = numbanks * 32; ++ if (irqs > NVIC_MAX_IRQ) ++ irqs = NVIC_MAX_IRQ; ++ ++ bank_data = kzalloc(sizeof(*bank_data) * numbanks, GFP_KERNEL); ++ if (!bank_data) { ++ pr_warn("Failed to allocate chip data"); ++ goto err_alloc_bank_data; ++ } ++ for (i = 0; i < numbanks; ++i) ++ bank_data[i].base = nvic_base + 4 * i; ++ ++ irq_base = irq_alloc_descs_from(16, irqs, numa_node_id()); ++ if (irq_base < 0) { ++ pr_warn("Cannot allocate irq_descs\n"); ++ ret = irq_base; ++ goto err_irq_alloc_descs; ++ } ++ if (irq_base != 16) { ++ /* ++ * The entry code just passes the exception number (i.e. irq ++ * number + 16) to asm_do_IRQ, so the offset needs to be fixed ++ * here. ++ */ ++ pr_warn("Failed to allocate irq_descs at offset 16\n"); ++ goto err_wrong_irq_base; ++ } ++ ++ irq_domain = irq_domain_add_legacy(node, irqs, irq_base, 0, ++ &irq_domain_simple_ops, NULL); ++ if (!irq_domain) { ++ pr_warn("Failed to allocate irq domain\n"); ++ goto err_domain_add; ++ } ++ ++ /* Disable all interrupts */ ++ for (i = 0; i < irqs; i += 32) ++ writel_relaxed(~0, nvic_base + NVIC_ICER + i * 4 / 32); ++ ++ /* Set priority on all interrupts */ ++ for (i = 0; i < irqs; i += 4) ++ writel_relaxed(0, nvic_base + NVIC_IPR + i); ++ ++ /* Setup the Linux IRQ subsystem */ ++ for (i = 0; i < irqs; i++) { ++ irq_set_chip_and_handler(irq_base + i, &nvic_chip, ++ handle_fasteoi_irq); ++ irq_set_chip_data(irq_base + i, bank_data + i / 32); ++ set_irq_flags(irq_base + i, IRQF_VALID | IRQF_PROBE); ++ } ++ ++ return 0; ++ ++err_domain_add: ++err_wrong_irq_base: ++ ++ irq_free_descs(irq_base, irqs - 16); ++err_irq_alloc_descs: ++ ++ kfree(bank_data); ++err_alloc_bank_data: ++ ++ return ret; ++} ++ ++static int __init nvic_of_init(struct device_node *node, ++ struct device_node *parent) ++{ ++ void __iomem *nvic_base; ++ ++ if (!node) ++ return -ENODEV; ++ ++ nvic_base = of_iomap(node, 0); ++ if (!nvic_base) { ++ pr_warn("unable to map nvic registers\n"); ++ return -ENOMEM; ++ } ++ ++ return nvic_init_bases(node, nvic_base); ++} ++IRQCHIP_DECLARE(armv7m_nvic, "arm,armv7m-nvic", nvic_of_init); diff --git a/patches/linux-3.9-rc1/0002-ARM-Add-base-support-for-ARMv7-M.patch b/patches/linux-3.9-rc1/0002-ARM-Add-base-support-for-ARMv7-M.patch new file mode 100644 index 0000000..c5e67e5 --- /dev/null +++ b/patches/linux-3.9-rc1/0002-ARM-Add-base-support-for-ARMv7-M.patch @@ -0,0 +1,770 @@ +From 79f338d22bae92074cb62de41e349265414d9d96 Mon Sep 17 00:00:00 2001 +From: Catalin Marinas +Date: Fri, 21 May 2010 18:06:41 +0100 +Subject: [PATCH 02/18] ARM: Add base support for ARMv7-M +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds the base support for the ARMv7-M +architecture. It consists of the corresponding arch/arm/mm/ files and +various #ifdef's around the kernel. Exception handling is implemented by +a subsequent patch. + +[ukleinek: squash in some changes originating from commit + +b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System) + +from the v2.6.33-arm1 patch stack, port to post 3.6, drop zImage +support, drop reorganisation of pt_regs, assert CONFIG_V7M doesn't leak +into installed headers and a few cosmetic changes] + +Signed-off-by: Catalin Marinas +Signed-off-by: Uwe Kleine-König +Forwarded: id:1363901310-9474-2-git-send-email-u.kleine-koenig@pengutronix.de (v9) +--- + arch/arm/include/asm/assembler.h | 17 +++- + arch/arm/include/asm/cputype.h | 12 ++- + arch/arm/include/asm/glue-cache.h | 27 ++++++ + arch/arm/include/asm/glue-df.h | 8 ++ + arch/arm/include/asm/glue-proc.h | 9 ++ + arch/arm/include/asm/irqflags.h | 22 +++-- + arch/arm/include/asm/ptrace.h | 4 + + arch/arm/include/asm/system_info.h | 1 + + arch/arm/include/asm/v7m.h | 47 +++++++++++ + arch/arm/include/uapi/asm/ptrace.h | 35 ++++++-- + arch/arm/kernel/head-nommu.S | 10 ++- + arch/arm/kernel/setup.c | 17 +++- + arch/arm/kernel/traps.c | 2 + + arch/arm/mm/cache-nop.S | 53 ++++++++++++ + arch/arm/mm/nommu.c | 2 + + arch/arm/mm/proc-v7m.S | 167 +++++++++++++++++++++++++++++++++++++ + 16 files changed, 412 insertions(+), 21 deletions(-) + create mode 100644 arch/arm/include/asm/v7m.h + create mode 100644 arch/arm/mm/cache-nop.S + create mode 100644 arch/arm/mm/proc-v7m.S + +diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h +index 05ee9ee..a5fef71 100644 +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -136,7 +136,11 @@ + * assumes FIQs are enabled, and that the processor is in SVC mode. + */ + .macro save_and_disable_irqs, oldcpsr ++#ifdef CONFIG_CPU_V7M ++ mrs \oldcpsr, primask ++#else + mrs \oldcpsr, cpsr ++#endif + disable_irq + .endm + +@@ -150,7 +154,11 @@ + * guarantee that this will preserve the flags. + */ + .macro restore_irqs_notrace, oldcpsr ++#ifdef CONFIG_CPU_V7M ++ msr primask, \oldcpsr ++#else + msr cpsr_c, \oldcpsr ++#endif + .endm + + .macro restore_irqs, oldcpsr +@@ -229,7 +237,14 @@ + #endif + .endm + +-#ifdef CONFIG_THUMB2_KERNEL ++#if defined(CONFIG_CPU_V7M) ++ /* ++ * setmode is used to assert to be in svc mode during boot. For v7-M ++ * this is done in __v7m_setup, so setmode can be empty here. ++ */ ++ .macro setmode, mode, reg ++ .endm ++#elif defined(CONFIG_THUMB2_KERNEL) + .macro setmode, mode, reg + mov \reg, #\mode + msr cpsr_c, \reg +diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h +index 7652712..d7eb0fb 100644 +--- a/arch/arm/include/asm/cputype.h ++++ b/arch/arm/include/asm/cputype.h +@@ -106,7 +106,17 @@ static inline unsigned int __attribute_const__ read_cpuid_id(void) + return read_cpuid(CPUID_ID); + } + +-#else /* ifdef CONFIG_CPU_CP15 */ ++#elif defined(CONFIG_CPU_V7M) ++ ++#include ++#include ++ ++static inline unsigned int __attribute_const__ read_cpuid_id(void) ++{ ++ return readl(V7M_SCS_CPUID); ++} ++ ++#else /* ifdef CONFIG_CPU_CP15 / elif defined(CONFIG_CPU_V7M) */ + + static inline unsigned int __attribute_const__ read_cpuid_id(void) + { +diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h +index cca9f15..65c9faf 100644 +--- a/arch/arm/include/asm/glue-cache.h ++++ b/arch/arm/include/asm/glue-cache.h +@@ -125,10 +125,37 @@ + # endif + #endif + ++#if defined(CONFIG_CPU_V7M) ++# ifdef _CACHE ++# define MULTI_CACHE 1 ++# else ++# define _CACHE nop ++# endif ++#endif ++ + #if !defined(_CACHE) && !defined(MULTI_CACHE) + #error Unknown cache maintenance model + #endif + ++#ifndef __ASSEMBLER__ ++extern inline void nop_flush_icache_all(void) { } ++extern inline void nop_flush_kern_cache_all(void) { } ++extern inline void nop_flush_kern_cache_louis(void) { } ++extern inline void nop_flush_user_cache_all(void) { } ++extern inline void nop_flush_user_cache_range(unsigned long a, ++ unsigned long b, unsigned int c) { } ++ ++extern inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { } ++extern inline int nop_coherent_user_range(unsigned long a, ++ unsigned long b) { return 0; } ++extern inline void nop_flush_kern_dcache_area(void *a, size_t s) { } ++ ++extern inline void nop_dma_flush_range(const void *a, const void *b) { } ++ ++extern inline void nop_dma_map_area(const void *s, size_t l, int f) { } ++extern inline void nop_dma_unmap_area(const void *s, size_t l, int f) { } ++#endif ++ + #ifndef MULTI_CACHE + #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) + #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) +diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h +index b6e9f2c..6b70f1b 100644 +--- a/arch/arm/include/asm/glue-df.h ++++ b/arch/arm/include/asm/glue-df.h +@@ -95,6 +95,14 @@ + # endif + #endif + ++#ifdef CONFIG_CPU_ABRT_NOMMU ++# ifdef CPU_DABORT_HANDLER ++# define MULTI_DABORT 1 ++# else ++# define CPU_DABORT_HANDLER nommu_early_abort ++# endif ++#endif ++ + #ifndef CPU_DABORT_HANDLER + #error Unknown data abort handler type + #endif +diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h +index ac1dd54..f2f39bc 100644 +--- a/arch/arm/include/asm/glue-proc.h ++++ b/arch/arm/include/asm/glue-proc.h +@@ -230,6 +230,15 @@ + # endif + #endif + ++#ifdef CONFIG_CPU_V7M ++# ifdef CPU_NAME ++# undef MULTI_CPU ++# define MULTI_CPU ++# else ++# define CPU_NAME cpu_v7m ++# endif ++#endif ++ + #ifndef MULTI_CPU + #define cpu_proc_init __glue(CPU_NAME,_proc_init) + #define cpu_proc_fin __glue(CPU_NAME,_proc_fin) +diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h +index 1e6cca5..3b763d6 100644 +--- a/arch/arm/include/asm/irqflags.h ++++ b/arch/arm/include/asm/irqflags.h +@@ -8,6 +8,16 @@ + /* + * CPU interrupt mask handling. + */ ++#ifdef CONFIG_CPU_V7M ++#define IRQMASK_REG_NAME_R "primask" ++#define IRQMASK_REG_NAME_W "primask" ++#define IRQMASK_I_BIT 1 ++#else ++#define IRQMASK_REG_NAME_R "cpsr" ++#define IRQMASK_REG_NAME_W "cpsr_c" ++#define IRQMASK_I_BIT PSR_I_BIT ++#endif ++ + #if __LINUX_ARM_ARCH__ >= 6 + + static inline unsigned long arch_local_irq_save(void) +@@ -15,7 +25,7 @@ static inline unsigned long arch_local_irq_save(void) + unsigned long flags; + + asm volatile( +- " mrs %0, cpsr @ arch_local_irq_save\n" ++ " mrs %0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\n" + " cpsid i" + : "=r" (flags) : : "memory", "cc"); + return flags; +@@ -129,7 +139,7 @@ static inline unsigned long arch_local_save_flags(void) + { + unsigned long flags; + asm volatile( +- " mrs %0, cpsr @ local_save_flags" ++ " mrs %0, " IRQMASK_REG_NAME_R " @ local_save_flags" + : "=r" (flags) : : "memory", "cc"); + return flags; + } +@@ -140,7 +150,7 @@ static inline unsigned long arch_local_save_flags(void) + static inline void arch_local_irq_restore(unsigned long flags) + { + asm volatile( +- " msr cpsr_c, %0 @ local_irq_restore" ++ " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore" + : + : "r" (flags) + : "memory", "cc"); +@@ -148,8 +158,8 @@ static inline void arch_local_irq_restore(unsigned long flags) + + static inline int arch_irqs_disabled_flags(unsigned long flags) + { +- return flags & PSR_I_BIT; ++ return flags & IRQMASK_I_BIT; + } + +-#endif +-#endif ++#endif /* ifdef __KERNEL__ */ ++#endif /* ifndef __ASM_ARM_IRQFLAGS_H */ +diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h +index 3d52ee1..04c99f3 100644 +--- a/arch/arm/include/asm/ptrace.h ++++ b/arch/arm/include/asm/ptrace.h +@@ -45,6 +45,7 @@ struct pt_regs { + */ + static inline int valid_user_regs(struct pt_regs *regs) + { ++#ifndef CONFIG_CPU_V7M + unsigned long mode = regs->ARM_cpsr & MODE_MASK; + + /* +@@ -67,6 +68,9 @@ static inline int valid_user_regs(struct pt_regs *regs) + regs->ARM_cpsr |= USR_MODE; + + return 0; ++#else /* ifndef CONFIG_CPU_V7M */ ++ return 1; ++#endif + } + + static inline long regs_return_value(struct pt_regs *regs) +diff --git a/arch/arm/include/asm/system_info.h b/arch/arm/include/asm/system_info.h +index dfd386d..720ea03 100644 +--- a/arch/arm/include/asm/system_info.h ++++ b/arch/arm/include/asm/system_info.h +@@ -11,6 +11,7 @@ + #define CPU_ARCH_ARMv5TEJ 7 + #define CPU_ARCH_ARMv6 8 + #define CPU_ARCH_ARMv7 9 ++#define CPU_ARCH_ARMv7M 10 + + #ifndef __ASSEMBLY__ + +diff --git a/arch/arm/include/asm/v7m.h b/arch/arm/include/asm/v7m.h +new file mode 100644 +index 0000000..e12b887 +--- /dev/null ++++ b/arch/arm/include/asm/v7m.h +@@ -0,0 +1,47 @@ ++/* ++ * Common defines for v7m cpus ++ */ ++#define V7M_SCS_ICTR IOMEM(0xe000e004) ++#define V7M_SCS_ICTR_INTLINESNUM_MASK 0x0000000f ++ ++#define V7M_SCS_CPUID IOMEM(0xe000ed00) ++ ++#define V7M_SCS_ICSR IOMEM(0xe000ed04) ++#define V7M_SCS_ICSR_PENDSVSET (1 << 28) ++#define V7M_SCS_ICSR_PENDSVCLR (1 << 27) ++#define V7M_SCS_ICSR_RETTOBASE (1 << 11) ++ ++#define V7M_SCS_VTOR IOMEM(0xe000ed08) ++ ++#define V7M_SCS_SCR IOMEM(0xe000ed10) ++#define V7M_SCS_SCR_SLEEPDEEP (1 << 2) ++ ++#define V7M_SCS_CCR IOMEM(0xe000ed14) ++#define V7M_SCS_CCR_STKALIGN (1 << 9) ++ ++#define V7M_SCS_SHPR2 IOMEM(0xe000ed1c) ++#define V7M_SCS_SHPR3 IOMEM(0xe000ed20) ++ ++#define V7M_SCS_SHCSR IOMEM(0xe000ed24) ++#define V7M_SCS_SHCSR_USGFAULTENA (1 << 18) ++#define V7M_SCS_SHCSR_BUSFAULTENA (1 << 17) ++#define V7M_SCS_SHCSR_MEMFAULTENA (1 << 16) ++ ++#define V7M_xPSR_FPALIGN 0x00000200 ++ ++#define EXC_RET_SBOP 0xffffffe1 ++#define EXC_RET_FRAMETYPE_MASK 0x00000010 ++#define EXC_RET_FRAMETYPE__BASIC 0x00000010 ++#define EXC_RET_MODE_MASK 0x00000008 ++#define EXC_RET_MODE__HANDLER 0x00000000 ++#define EXC_RET_MODE__THREAD 0x00000008 ++#define EXC_RET_STACK_MASK 0x00000004 ++#define EXC_RET_STACK__MAIN 0x00000000 ++#define EXC_RET_STACK__PROCESS 0x00000004 ++ ++#define EXC_RET_HANDLERMODE_MAINSTACK \ ++ (EXC_RET_SBOP | EXC_RET_FRAMETYPE__BASIC | EXC_RET_MODE__HANDLER | EXC_RET_STACK__MAIN) ++#define EXC_RET_THREADMODE_MAINSTACK \ ++ (EXC_RET_SBOP | EXC_RET_FRAMETYPE__BASIC | EXC_RET_MODE__THREAD | EXC_RET_STACK__MAIN) ++#define EXC_RET_THREADMODE_PROCESSSTACK \ ++ (EXC_RET_SBOP | EXC_RET_FRAMETYPE__BASIC | EXC_RET_MODE__THREAD | EXC_RET_STACK__PROCESS) +diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h +index 96ee092..5af0ed1 100644 +--- a/arch/arm/include/uapi/asm/ptrace.h ++++ b/arch/arm/include/uapi/asm/ptrace.h +@@ -34,28 +34,47 @@ + + /* + * PSR bits ++ * Note on V7M there is no mode contained in the PSR + */ + #define USR26_MODE 0x00000000 + #define FIQ26_MODE 0x00000001 + #define IRQ26_MODE 0x00000002 + #define SVC26_MODE 0x00000003 ++#if defined(__KERNEL__) && defined(CONFIG_CPU_V7M) ++/* ++ * Use 0 here to get code right that creates a userspace ++ * or kernel space thread. ++ */ ++#define USR_MODE 0x00000000 ++#define SVC_MODE 0x00000000 ++#else + #define USR_MODE 0x00000010 ++#define SVC_MODE 0x00000013 ++#endif + #define FIQ_MODE 0x00000011 + #define IRQ_MODE 0x00000012 +-#define SVC_MODE 0x00000013 + #define ABT_MODE 0x00000017 + #define HYP_MODE 0x0000001a + #define UND_MODE 0x0000001b + #define SYSTEM_MODE 0x0000001f + #define MODE32_BIT 0x00000010 + #define MODE_MASK 0x0000001f +-#define PSR_T_BIT 0x00000020 +-#define PSR_F_BIT 0x00000040 +-#define PSR_I_BIT 0x00000080 +-#define PSR_A_BIT 0x00000100 +-#define PSR_E_BIT 0x00000200 +-#define PSR_J_BIT 0x01000000 +-#define PSR_Q_BIT 0x08000000 ++ ++#define V4_PSR_T_BIT 0x00000020 /* >= V4T, but not V7M */ ++#define V7M_PSR_T_BIT 0x01000000 ++#if defined(__KERNEL__) && defined(CONFIG_CPU_V7M) ++#define PSR_T_BIT V7M_PSR_T_BIT ++#else ++/* for compatibility */ ++#define PSR_T_BIT V4_PSR_T_BIT ++#endif ++ ++#define PSR_F_BIT 0x00000040 /* >= V4, but not V7M */ ++#define PSR_I_BIT 0x00000080 /* >= V4, but not V7M */ ++#define PSR_A_BIT 0x00000100 /* >= V6, but not V7M */ ++#define PSR_E_BIT 0x00000200 /* >= V6, but not V7M */ ++#define PSR_J_BIT 0x01000000 /* >= V5J, but not V7M */ ++#define PSR_Q_BIT 0x08000000 /* >= V5E, including V7M */ + #define PSR_V_BIT 0x10000000 + #define PSR_C_BIT 0x20000000 + #define PSR_Z_BIT 0x40000000 +diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S +index 6a2e09c..e2988bb 100644 +--- a/arch/arm/kernel/head-nommu.S ++++ b/arch/arm/kernel/head-nommu.S +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + /* + * Kernel startup entry point. +@@ -50,10 +51,13 @@ ENTRY(stext) + + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode + @ and irqs disabled +-#ifndef CONFIG_CPU_CP15 +- ldr r9, =CONFIG_PROCESSOR_ID +-#else ++#if defined(CONFIG_CPU_CP15) + mrc p15, 0, r9, c0, c0 @ get processor id ++#elif defined(CONFIG_CPU_V7M) ++ ldr r9, =V7M_SCS_CPUID ++ ldr r9, [r9] ++#else ++ ldr r9, =CONFIG_PROCESSOR_ID + #endif + bl __lookup_processor_type @ r5=procinfo r9=cpuid + movs r10, r5 @ invalid processor (r5=0)? +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index 1cc9e17..8291245 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -128,7 +128,9 @@ struct stack { + u32 und[3]; + } ____cacheline_aligned; + ++#ifndef CONFIG_CPU_V7M + static struct stack stacks[NR_CPUS]; ++#endif + + char elf_platform[ELF_PLATFORM_SIZE]; + EXPORT_SYMBOL(elf_platform); +@@ -207,7 +209,7 @@ static const char *proc_arch[] = { + "5TEJ", + "6TEJ", + "7", +- "?(11)", ++ "7M", + "?(12)", + "?(13)", + "?(14)", +@@ -216,6 +218,12 @@ static const char *proc_arch[] = { + "?(17)", + }; + ++#ifdef CONFIG_CPU_V7M ++static int __get_cpu_architecture(void) ++{ ++ return CPU_ARCH_ARMv7M; ++} ++#else + static int __get_cpu_architecture(void) + { + int cpu_arch; +@@ -248,6 +256,7 @@ static int __get_cpu_architecture(void) + + return cpu_arch; + } ++#endif + + int __pure cpu_architecture(void) + { +@@ -293,7 +302,9 @@ static void __init cacheid_init(void) + { + unsigned int arch = cpu_architecture(); + +- if (arch >= CPU_ARCH_ARMv6) { ++ if (arch == CPU_ARCH_ARMv7M) { ++ cacheid = 0; ++ } else if (arch >= CPU_ARCH_ARMv6) { + unsigned int cachetype = read_cpuid_cachetype(); + if ((cachetype & (7 << 29)) == 4 << 29) { + /* ARMv7 register format */ +@@ -375,6 +386,7 @@ static void __init feat_v6_fixup(void) + */ + void cpu_init(void) + { ++#ifndef CONFIG_CPU_V7M + unsigned int cpu = smp_processor_id(); + struct stack *stk = &stacks[cpu]; + +@@ -425,6 +437,7 @@ void cpu_init(void) + "I" (offsetof(struct stack, und[0])), + PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) + : "r14"); ++#endif + } + + int __cpu_logical_map[NR_CPUS]; +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index 1c08911..3990eaa 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -819,6 +819,7 @@ static void __init kuser_get_tls_init(unsigned long vectors) + + void __init early_trap_init(void *vectors_base) + { ++#ifndef CONFIG_CPU_V7M + unsigned long vectors = (unsigned long)vectors_base; + extern char __stubs_start[], __stubs_end[]; + extern char __vectors_start[], __vectors_end[]; +@@ -850,4 +851,5 @@ void __init early_trap_init(void *vectors_base) + + flush_icache_range(vectors, vectors + PAGE_SIZE); + modify_domain(DOMAIN_USER, DOMAIN_CLIENT); ++#endif + } +diff --git a/arch/arm/mm/cache-nop.S b/arch/arm/mm/cache-nop.S +new file mode 100644 +index 0000000..543b930 +--- /dev/null ++++ b/arch/arm/mm/cache-nop.S +@@ -0,0 +1,53 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include "proc-macros.S" ++ ++ENTRY(nop_flush_icache_all) ++ mov pc, lr ++ENDPROC(nop_flush_icache_all) ++ ++ .globl nop_flush_kern_cache_all ++ .equ nop_flush_kern_cache_all, nop_flush_icache_all ++ ++ .globl nop_flush_kern_cache_louis ++ .equ nop_flush_kern_cache_louis, nop_flush_icache_all ++ ++ .globl nop_flush_user_cache_all ++ .equ nop_flush_user_cache_all, nop_flush_icache_all ++ ++ .globl nop_flush_user_cache_range ++ .equ nop_flush_user_cache_range, nop_flush_icache_all ++ ++ .globl nop_coherent_kern_range ++ .equ nop_coherent_kern_range, nop_flush_icache_all ++ ++ENTRY(nop_coherent_user_range) ++ mov r0, 0 ++ mov pc, lr ++ENDPROC(nop_coherent_user_range) ++ ++ .globl nop_flush_kern_dcache_area ++ .equ nop_flush_kern_dcache_area, nop_flush_icache_all ++ ++ .globl nop_dma_flush_range ++ .equ nop_dma_flush_range, nop_flush_icache_all ++ ++ .globl nop_dma_map_area ++ .equ nop_dma_map_area, nop_flush_icache_all ++ ++ .globl nop_dma_unmap_area ++ .equ nop_dma_unmap_area, nop_flush_icache_all ++ ++ __INITDATA ++ ++ @ define struct cpu_cache_fns (see and proc-macros.S) ++ define_cache_functions nop +diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c +index d51225f..4bc8ae5 100644 +--- a/arch/arm/mm/nommu.c ++++ b/arch/arm/mm/nommu.c +@@ -20,12 +20,14 @@ + + void __init arm_mm_memblock_reserve(void) + { ++#ifndef CONFIG_CPU_V7M + /* + * Register the exception vector page. + * some architectures which the DRAM is the exception vector to trap, + * alloc_page breaks with error, although it is not NULL, but "0." + */ + memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE); ++#endif + } + + void __init sanity_check_meminfo(void) +diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S +new file mode 100644 +index 0000000..c2b68d3 +--- /dev/null ++++ b/arch/arm/mm/proc-v7m.S +@@ -0,0 +1,167 @@ ++/* ++ * linux/arch/arm/mm/proc-v7m.S ++ * ++ * Copyright (C) 2008 ARM Ltd. ++ * Copyright (C) 2001 Deep Blue Solutions 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. ++ * ++ * This is the "shell" of the ARMv7-M processor support. ++ */ ++#include ++#include ++#include ++ ++ENTRY(cpu_v7m_proc_init) ++ mov pc, lr ++ENDPROC(cpu_v7m_proc_init) ++ ++ENTRY(cpu_v7m_proc_fin) ++ mov pc, lr ++ENDPROC(cpu_v7m_proc_fin) ++ ++/* ++ * cpu_v7m_reset(loc) ++ * ++ * Perform a soft reset of the system. Put the CPU into the ++ * same state as it would be if it had been reset, and branch ++ * to what would be the reset vector. ++ * ++ * - loc - location to jump to for soft reset ++ */ ++ .align 5 ++ENTRY(cpu_v7m_reset) ++ mov pc, r0 ++ENDPROC(cpu_v7m_reset) ++ ++/* ++ * cpu_v7m_do_idle() ++ * ++ * Idle the processor (eg, wait for interrupt). ++ * ++ * IRQs are already disabled. ++ */ ++ENTRY(cpu_v7m_do_idle) ++ wfi ++ mov pc, lr ++ENDPROC(cpu_v7m_do_idle) ++ ++ENTRY(cpu_v7m_dcache_clean_area) ++ mov pc, lr ++ENDPROC(cpu_v7m_dcache_clean_area) ++ ++/* ++ * There is no MMU, so here is nothing to do. ++ */ ++ENTRY(cpu_v7m_switch_mm) ++ mov pc, lr ++ENDPROC(cpu_v7m_switch_mm) ++ ++cpu_v7m_name: ++ .ascii "ARMv7-M Processor" ++ .align ++ ++ .section ".text.init", #alloc, #execinstr ++ ++/* ++ * __v7m_setup ++ * ++ * This should be able to cover all ARMv7-M cores. ++ */ ++__v7m_setup: ++ @ Configure the vector table base address ++ ldr r0, =V7M_SCS_VTOR @ vector table base address ++ ldr r12, =vector_table ++ str r12, [r0] ++ ++ @ enable UsageFault, BusFault and MemManage fault. ++ ldr r5, [r0, #(V7M_SCS_SHCSR - V7M_SCS_VTOR)] ++ orr r5, #(V7M_SCS_SHCSR_USGFAULTENA | V7M_SCS_SHCSR_BUSFAULTENA | V7M_SCS_SHCSR_MEMFAULTENA) ++ str r5, [r0, #(V7M_SCS_SHCSR - V7M_SCS_VTOR)] ++ ++ @ Lower the priority of the SVC and PendSV exceptions ++ ldr r0, =V7M_SCS_SHPR2 ++ mov r5, #0x80000000 ++ str r5, [r0] @ set SVC priority ++ ldr r0, =V7M_SCS_SHPR3 ++ mov r5, #0x00800000 ++ str r5, [r0] @ set PendSV priority ++ ++ @ SVC to run the kernel in this mode ++ adr r0, BSYM(1f) ++ ldr r5, [r12, #11 * 4] @ read the SVC vector entry ++ str r0, [r12, #11 * 4] @ write the temporary SVC vector entry ++ mov r6, lr @ save LR ++ mov r7, sp @ save SP ++ ldr sp, =__v7m_setup_stack_top ++ cpsie i ++ svc #0 ++1: cpsid i ++ str r5, [r12, #11 * 4] @ restore the original SVC vector entry ++ mov lr, r6 @ restore LR ++ mov sp, r7 @ restore SP ++ ++ @ Special-purpose control register ++ mov r0, #1 ++ msr control, r0 @ Thread mode has unpriviledged access ++ ++ @ Configure the System Control Register ++ ldr r0, =V7M_SCS_CCR @ system control register ++ ldr r12, [r0] ++ orr r12, #V7M_SCS_CCR_STKALIGN ++ str r12, [r0] ++ mov pc, lr ++ENDPROC(__v7m_setup) ++ ++ .align 2 ++ .type v7m_processor_functions, #object ++ENTRY(v7m_processor_functions) ++ .word nommu_early_abort ++ .word cpu_v7m_proc_init ++ .word cpu_v7m_proc_fin ++ .word cpu_v7m_reset ++ .word cpu_v7m_do_idle ++ .word cpu_v7m_dcache_clean_area ++ .word cpu_v7m_switch_mm ++ .word 0 @ cpu_v7m_set_pte_ext ++ .word legacy_pabort ++ .size v7m_processor_functions, . - v7m_processor_functions ++ ++ .type cpu_arch_name, #object ++cpu_arch_name: ++ .asciz "armv7m" ++ .size cpu_arch_name, . - cpu_arch_name ++ ++ .type cpu_elf_name, #object ++cpu_elf_name: ++ .asciz "v7m" ++ .size cpu_elf_name, . - cpu_elf_name ++ .align ++ ++ .section ".proc.info.init", #alloc, #execinstr ++ ++ /* ++ * Match any ARMv7-M processor core. ++ */ ++ .type __v7m_proc_info, #object ++__v7m_proc_info: ++ .long 0x000f0000 @ Required ID value ++ .long 0x000f0000 @ Mask for ID ++ .long 0 @ proc_info_list.__cpu_mm_mmu_flags ++ .long 0 @ proc_info_list.__cpu_io_mmu_flags ++ b __v7m_setup @ proc_info_list.__cpu_flush ++ .long cpu_arch_name ++ .long cpu_elf_name ++ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP ++ .long cpu_v7m_name ++ .long v7m_processor_functions @ proc_info_list.proc ++ .long 0 @ proc_info_list.tlb ++ .long 0 @ proc_info_list.user ++ .long nop_cache_fns @ proc_info_list.cache ++ .size __v7m_proc_info, . - __v7m_proc_info ++ ++__v7m_setup_stack: ++ .space 4 * 8 @ 8 registers ++__v7m_setup_stack_top: diff --git a/patches/linux-3.9-rc1/0003-ARM-ARMv7-M-Add-support-for-exception-handling.patch b/patches/linux-3.9-rc1/0003-ARM-ARMv7-M-Add-support-for-exception-handling.patch new file mode 100644 index 0000000..1799e57 --- /dev/null +++ b/patches/linux-3.9-rc1/0003-ARM-ARMv7-M-Add-support-for-exception-handling.patch @@ -0,0 +1,347 @@ +From 58351399de4f2e4471854733adb3befdc1dd321d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Fri, 21 May 2010 18:06:42 +0100 +Subject: [PATCH 03/18] ARM: ARMv7-M: Add support for exception handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch implements the exception handling for the ARMv7-M +architecture (pretty different from the A or R profiles). + +It bases on work done earlier by Catalin for 2.6.33 but was nearly +completely rewritten to use a pt_regs layout compatible to the A +profile. + +Signed-off-by: Catalin Marinas +Signed-off-by: Uwe Kleine-König +Forwarded: id:1363901310-9474-3-git-send-email-u.kleine-koenig@pengutronix.de (v9) +--- + arch/arm/kernel/entry-common.S | 4 ++ + arch/arm/kernel/entry-header.S | 120 ++++++++++++++++++++++++++++++++++ + arch/arm/kernel/entry-v7m.S | 142 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 266 insertions(+) + create mode 100644 arch/arm/kernel/entry-v7m.S + +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index 3248cde..c45e002 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -339,6 +339,9 @@ ENDPROC(ftrace_stub) + + .align 5 + ENTRY(vector_swi) ++#ifdef CONFIG_CPU_V7M ++ v7m_exception_entry ++#else + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0 - r12 + ARM( add r8, sp, #S_PC ) +@@ -349,6 +352,7 @@ ENTRY(vector_swi) + str lr, [sp, #S_PC] @ Save calling PC + str r8, [sp, #S_PSR] @ Save CPSR + str r0, [sp, #S_OLD_R0] @ Save OLD_R0 ++#endif + zero_fp + + /* +diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S +index 9a8531e..4caccb4 100644 +--- a/arch/arm/kernel/entry-header.S ++++ b/arch/arm/kernel/entry-header.S +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + @ Bad Abort numbers + @ ----------------- +@@ -44,6 +45,115 @@ + #endif + .endm + ++#ifdef CONFIG_CPU_V7M ++/* ++ * ARMv7-M exception entry/exit macros. ++ * ++ * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are ++ * automatically saved on the current stack (32 words) before ++ * switching to the exception stack (SP_main). ++ * ++ * If exception is taken while in user mode, SP_main is ++ * empty. Otherwise, SP_main is aligned to 64 bit automatically ++ * (CCR.STKALIGN set). ++ * ++ * Linux assumes that the interrupts are disabled when entering an ++ * exception handler and it may BUG if this is not the case. Interrupts ++ * are disabled during entry and reenabled in the exit macro. ++ * ++ * v7m_exception_slow_exit is used when returning from SVC or PendSV. ++ * When returning to kernel mode, we don't return from exception. ++ */ ++ .macro v7m_exception_entry ++ @ determine the location of the registers saved by the core during ++ @ exception entry. Depending on the mode the cpu was in when the ++ @ exception happend that is either on the main or the process stack. ++ @ Bit 2 of EXC_RETURN stored in the lr register specifies which stack ++ @ was used. ++ tst lr, #EXC_RET_STACK_MASK ++ mrsne r12, psp ++ moveq r12, sp ++ ++ @ we cannot rely on r0-r3 and r12 matching the value saved in the ++ @ exception frame because of tail-chaining. So these have to be ++ @ reloaded. ++ ldmia r12!, {r0-r3} ++ ++ @ Linux expects to have irqs off. Do it here before taking stack space ++ cpsid i ++ ++ sub sp, #S_FRAME_SIZE-S_IP ++ stmdb sp!, {r0-r11} ++ ++ @ load saved r12, lr, return address and xPSR. ++ @ r0-r7 are used for signals and never touched from now on. Clobbering ++ @ r8-r12 is OK. ++ mov r9, r12 ++ ldmia r9!, {r8, r10-r12} ++ ++ @ calculate the original stack pointer value. ++ @ r9 currently points to the memory location just above the auto saved ++ @ xPSR. ++ @ The cpu might automatically 8-byte align the stack. Bit 9 ++ @ of the saved xPSR specifies if stack aligning took place. In this case ++ @ another 32-bit value is included in the stack. ++ ++ tst r12, V7M_xPSR_FPALIGN ++ addne r9, r9, #4 ++ ++ @ store saved r12 using str to have a register to hold the base for stm ++ str r8, [sp, #S_IP] ++ add r8, sp, #S_SP ++ @ store r13-r15, xPSR ++ stmia r8!, {r9-r12} ++ @ store old_r0 ++ str r0, [r8] ++ .endm ++ ++ ++/* ++ * We won't return to kernel space here because a kernel thread runs in SVCALL ++ * context and so cannot be preempted by PENDSV. ++ */ ++ .macro v7m_exception_slow_exit ret_r0 ++ cpsid i ++ ldr lr, =EXC_RET_THREADMODE_PROCESSSTACK ++ ++ @ read original r12, sp, lr, pc and xPSR ++ add r12, sp, #S_IP ++ ldmia r12, {r1-r5} ++ ++ @ an exception frame is always 8-byte aligned. To tell the hardware if ++ @ the sp to be restored is aligned or not set bit 9 of the saved xPSR ++ @ accordingly. ++ tst r2, #4 ++ subne r2, r2, #4 ++ orrne r5, V7M_xPSR_FPALIGN ++ biceq r5, V7M_xPSR_FPALIGN ++ ++ @ write basic exception frame ++ stmdb r2!, {r1, r3-r5} ++ ldmia sp, {r1, r3-r5} ++ .if \ret_r0 ++ stmdb r2!, {r0, r3-r5} ++ .else ++ stmdb r2!, {r1, r3-r5} ++ .endif ++ ++ @ restore process sp ++ msr psp, r2 ++ ++ @ restore original r4-r11 ++ ldmia sp!, {r0-r11} ++ ++ @ restore main sp ++ add sp, sp, #S_FRAME_SIZE-S_IP ++ ++ cpsie i ++ bx lr ++ .endm ++#endif /* CONFIG_CPU_V7M */ ++ + @ + @ Store/load the USER SP and LR registers by switching to the SYS + @ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not +@@ -131,6 +241,15 @@ + rfeia sp! + .endm + ++#ifdef CONFIG_CPU_V7M ++ .macro restore_user_regs, fast = 0, offset = 0 ++ @ XXX: clrex? ++ .if \offset ++ add sp, #\offset ++ .endif ++ v7m_exception_slow_exit ret_r0 = \fast ++ .endm ++#else /* ifdef CONFIG_CPU_V7M */ + .macro restore_user_regs, fast = 0, offset = 0 + clrex @ clear the exclusive monitor + mov r2, sp +@@ -147,6 +266,7 @@ + add sp, sp, #S_FRAME_SIZE - S_SP + movs pc, lr @ return & move spsr_svc into cpsr + .endm ++#endif /* ifdef CONFIG_CPU_V7M / else */ + + .macro get_thread_info, rd + mov \rd, sp +diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S +new file mode 100644 +index 0000000..9518c96 +--- /dev/null ++++ b/arch/arm/kernel/entry-v7m.S +@@ -0,0 +1,142 @@ ++/* ++ * linux/arch/arm/kernel/entry-v7m.S ++ * ++ * Copyright (C) 2008 ARM 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. ++ * ++ * Low-level vector interface routines for the ARMv7-M architecture ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "entry-header.S" ++ ++#ifdef CONFIG_TRACE_IRQFLAGS ++#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation" ++#endif ++ ++__invalid_entry: ++ v7m_exception_entry ++ adr r0, strerr ++ mrs r1, ipsr ++ mov r2, lr ++ bl printk ++ mov r0, sp ++ bl show_regs ++1: b 1b ++ENDPROC(__invalid_entry) ++ ++strerr: .asciz "\nUnhandled exception: IPSR = %08lx LR = %08lx\n" ++ ++ .align 2 ++__irq_entry: ++ v7m_exception_entry ++ ++ @ ++ @ Invoke the IRQ handler ++ @ ++ mrs r0, ipsr ++ ldr r1, =0x1ff ++ and r0, r1 ++ mov r1, sp ++ stmdb sp!, {lr} ++ @ routine called with r0 = irq number, r1 = struct pt_regs * ++ bl asm_do_IRQ ++ ++ pop {lr} ++ @ ++ @ Check for any pending work if returning to user ++ @ ++ ldr r1, =V7M_SCS_ICSR ++ ldr r0, [r1] ++ tst r0, V7M_SCS_ICSR_RETTOBASE ++ beq 2f ++ ++ get_thread_info tsk ++ ldr r2, [tsk, #TI_FLAGS] ++ tst r2, #_TIF_WORK_MASK ++ beq 2f @ no work pending ++ mov r0, #V7M_SCS_ICSR_PENDSVSET ++ str r0, [r1] @ raise PendSV ++ ++2: ++ @ registers r0-r3 and r12 are automatically restored on exception ++ @ return. r4-r7 were not clobbered in v7m_exception_entry so for ++ @ correctness they don't need to be restored. So only r8-r11 must be ++ @ restored here. The easiest way to do so is to restore r0-r7, too. ++ ldmia sp!, {r0-r11} ++ add sp, #S_FRAME_SIZE-S_IP ++ cpsie i ++ bx lr ++ENDPROC(__irq_entry) ++ ++__pendsv_entry: ++ v7m_exception_entry ++ ++ ldr r1, =V7M_SCS_ICSR ++ mov r0, #V7M_SCS_ICSR_PENDSVCLR ++ str r0, [r1] @ clear PendSV ++ ++ @ execute the pending work, including reschedule ++ get_thread_info tsk ++ mov why, #0 ++ b ret_to_user ++ENDPROC(__pendsv_entry) ++ ++/* ++ * Register switch for ARMv7-M processors. ++ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info ++ * previous and next are guaranteed not to be the same. ++ */ ++ENTRY(__switch_to) ++ .fnstart ++ .cantunwind ++ add ip, r1, #TI_CPU_SAVE ++ stmia ip!, {r4 - r11} @ Store most regs on stack ++ str sp, [ip], #4 ++ str lr, [ip], #4 ++ mov r5, r0 ++ add r4, r2, #TI_CPU_SAVE ++ ldr r0, =thread_notify_head ++ mov r1, #THREAD_NOTIFY_SWITCH ++ bl atomic_notifier_call_chain ++ mov ip, r4 ++ mov r0, r5 ++ ldmia ip!, {r4 - r11} @ Load all regs saved previously ++ ldr sp, [ip] ++ ldr pc, [ip, #4]! ++ .fnend ++ENDPROC(__switch_to) ++ ++ .data ++ .align 8 ++/* ++ * Vector table (64 words => 256 bytes natural alignment) ++ */ ++ENTRY(vector_table) ++ .long 0 @ 0 - Reset stack pointer ++ .long __invalid_entry @ 1 - Reset ++ .long __invalid_entry @ 2 - NMI ++ .long __invalid_entry @ 3 - HardFault ++ .long __invalid_entry @ 4 - MemManage ++ .long __invalid_entry @ 5 - BusFault ++ .long __invalid_entry @ 6 - UsageFault ++ .long __invalid_entry @ 7 - Reserved ++ .long __invalid_entry @ 8 - Reserved ++ .long __invalid_entry @ 9 - Reserved ++ .long __invalid_entry @ 10 - Reserved ++ .long vector_swi @ 11 - SVCall ++ .long __invalid_entry @ 12 - Debug Monitor ++ .long __invalid_entry @ 13 - Reserved ++ .long __pendsv_entry @ 14 - PendSV ++ .long __invalid_entry @ 15 - SysTick ++ .rept 64 - 16 ++ .long __irq_entry @ 16..64 - External Interrupts ++ .endr diff --git a/patches/linux-3.9-rc1/0004-ARM-ARMv7-M-Allow-the-building-of-new-kernel-port.patch b/patches/linux-3.9-rc1/0004-ARM-ARMv7-M-Allow-the-building-of-new-kernel-port.patch new file mode 100644 index 0000000..04173d5 --- /dev/null +++ b/patches/linux-3.9-rc1/0004-ARM-ARMv7-M-Allow-the-building-of-new-kernel-port.patch @@ -0,0 +1,170 @@ +From bf56c2f63fccf08ddf6b2f93911e68b15132e3fe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 21 Mar 2013 21:02:37 +0100 +Subject: [PATCH 04/18] ARM: ARMv7-M: Allow the building of new kernel port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch modifies the required Kconfig and Makefile files to allow the +building of kernel for Cortex-M3. + +Signed-off-by: Catalin Marinas +Signed-off-by: Uwe Kleine-König +Forwarded: id:1363901310-9474-4-git-send-email-u.kleine-koenig@pengutronix.de (v9) +--- + arch/arm/Kconfig | 4 ++-- + arch/arm/Kconfig-nommu | 2 +- + arch/arm/Makefile | 1 + + arch/arm/kernel/Makefile | 8 +++++++- + arch/arm/mm/Kconfig | 22 +++++++++++++++++++++- + arch/arm/mm/Makefile | 2 ++ + 6 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index dedf02b..7c8c607 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -9,7 +9,7 @@ config ARM + select BUILDTIME_EXTABLE_SORT if MMU + select CPU_PM if (SUSPEND || CPU_IDLE) + select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN && MMU +- select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI) ++ select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI) + select GENERIC_CLOCKEVENTS_BROADCAST if SMP + select GENERIC_IRQ_PROBE + select GENERIC_IRQ_SHOW +@@ -1685,7 +1685,7 @@ config SCHED_HRTICK + + config THUMB2_KERNEL + bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY +- depends on CPU_V7 && !CPU_V6 && !CPU_V6K ++ depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K + default y if CPU_THUMBONLY + select AEABI + select ARM_ASM_UNIFIED +diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu +index 2cef8e1..c859495 100644 +--- a/arch/arm/Kconfig-nommu ++++ b/arch/arm/Kconfig-nommu +@@ -28,7 +28,7 @@ config FLASH_SIZE + config PROCESSOR_ID + hex 'Hard wire the processor ID' + default 0x00007700 +- depends on !CPU_CP15 ++ depends on !(CPU_CP15 || CPU_V7M) + help + If processor has no CP15 register, this processor ID is + used instead of the auto-probing which utilizes the register. +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index ee4605f..f11b8da 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -59,6 +59,7 @@ comma = , + # Note that GCC does not numerically define an architecture version + # macro, but instead defines a whole series of macros which makes + # testing for a specific architecture or later rather impossible. ++arch-$(CONFIG_CPU_32v7M) :=-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m + arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) + arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) + # Only override the compiler option if ARMv6. The ARMv6K extensions are +diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile +index 5f3338e..00d703c 100644 +--- a/arch/arm/kernel/Makefile ++++ b/arch/arm/kernel/Makefile +@@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg + + # Object file lists. + +-obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \ ++obj-y := elf.o entry-common.o irq.o opcodes.o \ + process.o ptrace.o return_address.o sched_clock.o \ + setup.o signal.o stacktrace.o sys_arm.o time.o traps.o + +@@ -23,6 +23,12 @@ obj-$(CONFIG_ATAGS) += atags_parse.o + obj-$(CONFIG_ATAGS_PROC) += atags_proc.o + obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o + ++ifeq ($(CONFIG_CPU_V7M),y) ++obj-y += entry-v7m.o ++else ++obj-y += entry-armv.o ++endif ++ + obj-$(CONFIG_OC_ETM) += etm.o + obj-$(CONFIG_CPU_IDLE) += cpuidle.o + obj-$(CONFIG_ISA_DMA_API) += dma.o +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index cb812a1..9c3eac4 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -397,6 +397,16 @@ config CPU_V7 + select CPU_PABRT_V7 + select CPU_TLB_V7 if MMU + ++# ARMv7M ++config CPU_V7M ++ bool ++ select CPU_32v7M ++ select CPU_ABRT_NOMMU ++ select CPU_CACHE_NOP ++ select CPU_CACHE_VIPT ++ select CPU_PABRT_LEGACY ++ select CPU_THUMBONLY ++ + config CPU_THUMBONLY + bool + # There are no CPUs available with MMU that don't implement an ARM ISA: +@@ -441,6 +451,9 @@ config CPU_32v6K + config CPU_32v7 + bool + ++config CPU_32v7M ++ bool ++ + # The abort model + config CPU_ABRT_NOMMU + bool +@@ -494,6 +507,9 @@ config CPU_CACHE_V6 + config CPU_CACHE_V7 + bool + ++config CPU_CACHE_NOP ++ bool ++ + config CPU_CACHE_VIVT + bool + +@@ -616,7 +632,11 @@ config ARCH_DMA_ADDR_T_64BIT + + config ARM_THUMB + bool "Support Thumb user binaries" if !CPU_THUMBONLY +- depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON ++ depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || \ ++ CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || \ ++ CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || \ ++ CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || \ ++ CPU_V7 || CPU_FEROCEON || CPU_V7M + default y + help + Say Y if you want to include kernel support for running user space +diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile +index 4e333fa..317b575 100644 +--- a/arch/arm/mm/Makefile ++++ b/arch/arm/mm/Makefile +@@ -40,6 +40,7 @@ obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o + obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o + obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o + obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o ++obj-$(CONFIG_CPU_CACHE_NOP) += cache-nop.o + + AFLAGS_cache-v6.o :=-Wa,-march=armv6 + AFLAGS_cache-v7.o :=-Wa,-march=armv7-a +@@ -88,6 +89,7 @@ obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o + obj-$(CONFIG_CPU_V6) += proc-v6.o + obj-$(CONFIG_CPU_V6K) += proc-v6.o + obj-$(CONFIG_CPU_V7) += proc-v7.o ++obj-$(CONFIG_CPU_V7M) += proc-v7m.o + + AFLAGS_proc-v6.o :=-Wa,-march=armv6 + AFLAGS_proc-v7.o :=-Wa,-march=armv7-a diff --git a/patches/linux-3.9-rc1/0005-hwmon-efm32-adc-new-driver.patch b/patches/linux-3.9-rc1/0005-hwmon-efm32-adc-new-driver.patch new file mode 100644 index 0000000..53a8fbe --- /dev/null +++ b/patches/linux-3.9-rc1/0005-hwmon-efm32-adc-new-driver.patch @@ -0,0 +1,358 @@ +From f4be8d0c5c919a6eda9d36c7f35c3230cee24a56 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 9 Feb 2012 22:35:24 +0100 +Subject: [PATCH 05/18] hwmon/efm32-adc: new driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Uwe Kleine-König +--- + drivers/hwmon/Kconfig | 10 ++ + drivers/hwmon/Makefile | 1 + + drivers/hwmon/efm32-adc.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 314 insertions(+) + create mode 100644 drivers/hwmon/efm32-adc.c + +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 89ac1cb..d6d771b 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -344,6 +344,16 @@ config SENSORS_DA9055 + This driver can also be built as a module. If so, the module + will be called da9055-hwmon. + ++config SENSORS_EFM32_ADC ++ tristate "Energy Micro EFM32 ADC" ++ depends on ARCH_EFM32 ++ help ++ If you say yes here you get support for Energy Micro's ADC ++ build into their EFM32 SoCs ++ ++ This driver can also be built as a module. If so, the module ++ will be called efm32-adc. ++ + config SENSORS_I5K_AMB + tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" + depends on PCI +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index 8d6d97e..58b3c8b 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -48,6 +48,7 @@ obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o + obj-$(CONFIG_SENSORS_DME1737) += dme1737.o + obj-$(CONFIG_SENSORS_DS620) += ds620.o + obj-$(CONFIG_SENSORS_DS1621) += ds1621.o ++obj-$(CONFIG_SENSORS_EFM32_ADC) += efm32-adc.o + obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o + obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o + obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o +diff --git a/drivers/hwmon/efm32-adc.c b/drivers/hwmon/efm32-adc.c +new file mode 100644 +index 0000000..99d6b45 +--- /dev/null ++++ b/drivers/hwmon/efm32-adc.c +@@ -0,0 +1,303 @@ ++/* ++ * Energy Micro EFM32 adc ++ * ++ * Copyright (C) 2012 Uwe Kleine-Koenig for Pengutronix ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "efm32-adc" ++ ++#define ADC_CTRL 0x000 ++ ++#define ADC_CMD 0x004 ++#define ADC_CMD_SINGLESTART 0x00000001 ++#define ADC_CMD_SINGLESTOP 0x00000002 ++#define ADC_CMD_SCANSTART 0x00000004 ++#define ADC_CMD_SCANSTOP 0x00000008 ++ ++#define ADC_STATUS 0x008 ++#define ADC_STATUS_SINGLEDV 0x00010000 ++#define ADC_SINGLECTRL 0x00c ++#define ADC_SINGLEDATA 0x024 ++ ++#define ADC_IEN 0x014 ++#define ADC_IF 0x018 ++#define ADC_IFC 0x020 ++#define ADC_IF_SINGLE 0x00000001 ++ ++struct efm32_adc_ddata { ++ struct device *hwmondev; ++ void __iomem *base; ++ struct clk *clk; ++ unsigned int irq; ++ spinlock_t lock; ++ unsigned int busy; ++}; ++ ++static void efm32_adc_write32(struct efm32_adc_ddata *ddata, ++ u32 value, unsigned offset) ++{ ++ writel_relaxed(value, ddata->base + offset); ++} ++ ++static u32 efm32_adc_read32(struct efm32_adc_ddata *ddata, unsigned offset) ++{ ++ return readl_relaxed(ddata->base + offset); ++} ++ ++static ssize_t efm32_adc_show_name(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ return sprintf(buf, "efm32\n"); ++} ++ ++struct efm32_adc_irqdata { ++ struct efm32_adc_ddata *ddata; ++ struct completion done; ++}; ++ ++static irqreturn_t efm32_adc_irq(int irq, void *data) ++{ ++ struct efm32_adc_irqdata *irqdata = data; ++ u32 iflag = efm32_adc_read32(irqdata->ddata, ADC_IF); ++ ++ if (iflag & ADC_IF_SINGLE) { ++ efm32_adc_write32(irqdata->ddata, ADC_IF_SINGLE, ADC_IFC); ++ complete(&irqdata->done); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static int efm32_adc_read_single(struct device *dev, ++ struct device_attribute *devattr, unsigned int *val) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct efm32_adc_ddata *ddata = platform_get_drvdata(pdev); ++ int ret; ++ struct efm32_adc_irqdata irqdata = { .ddata = ddata, }; ++ u32 status; ++ unsigned long freq = clk_get_rate(ddata->clk); ++ ++ init_completion(&irqdata.done); ++ ++ spin_lock_irq(&ddata->lock); ++ if (ddata->busy) { ++ ret = -EBUSY; ++ goto out_unlock; ++ } ++ ++ /* XXX: this depends on CMU_HFPERCLKEN0.ADC being on. */ ++ efm32_adc_write32(ddata, ++ ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP, ADC_CMD); ++ efm32_adc_write32(ddata, ((freq - 1) / 1000000) << 16 | ++ ((freq / 400000) - 1) << 8, ADC_CTRL); ++ efm32_adc_write32(ddata, 0x800, ADC_SINGLECTRL); ++ efm32_adc_write32(ddata, ADC_IF_SINGLE, ADC_IFC); ++ efm32_adc_write32(ddata, ADC_CMD_SINGLESTART, ADC_CMD); ++ ++ ret = request_irq(ddata->irq, efm32_adc_irq, 0, DRIVER_NAME, &irqdata); ++ if (ret) { ++ efm32_adc_write32(ddata, ADC_CMD_SINGLESTOP, ADC_CMD); ++ goto out_unlock; ++ } ++ ++ efm32_adc_write32(ddata, ADC_IF_SINGLE, ADC_IEN); ++ ++ ddata->busy = 1; ++ ++ spin_unlock_irq(&ddata->lock); ++ ++ ret = wait_for_completion_interruptible_timeout(&irqdata.done, 2 * HZ); ++ ++ spin_lock_irq(&ddata->lock); ++ ++ efm32_adc_write32(ddata, 0, ADC_IEN); ++ free_irq(ddata->irq, &irqdata); ++ ++ if (ret < 0) ++ goto done_out_unlock; ++ ++ status = efm32_adc_read32(ddata, ADC_STATUS); ++ if (status & ADC_STATUS_SINGLEDV) { ++ *val = efm32_adc_read32(ddata, ADC_SINGLEDATA); ++ ret = 0; ++ } else ++ ret = -ETIMEDOUT; ++ ++done_out_unlock: ++ ddata->busy = 0; ++out_unlock: ++ spin_unlock_irq(&ddata->lock); ++ ++ return ret; ++} ++ ++static ssize_t efm32_adc_read_chan(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ unsigned int val; ++ int ret = efm32_adc_read_single(dev, devattr, &val); ++ ++ if (ret) ++ return ret; ++ ++ return sprintf(buf, "%u\n", val); ++} ++ ++static ssize_t efm32_adc_read_temp(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ unsigned int val; ++ int ret = efm32_adc_read_single(dev, devattr, &val); ++ /* ++ * XXX: get these via pdata or read them from the device information ++ * registers ++ */ ++ unsigned temp0 = 0x19 * 1000; ++ unsigned adc0 = 0x910; ++ ++ if (ret) ++ return ret; ++ ++ val = temp0 + DIV_ROUND_CLOSEST((adc0 - val) * 10000, 63); ++ ++ return sprintf(buf, "%u\n", val); ++} ++ ++static DEVICE_ATTR(name, S_IRUGO, efm32_adc_show_name, NULL); ++static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, efm32_adc_read_chan, NULL, 8); ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, efm32_adc_read_temp, NULL, 8); ++ ++static struct attribute *efm32_adc_attr[] = { ++ &dev_attr_name.attr, ++ &sensor_dev_attr_in8_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group efm32_adc_group = { ++ .attrs = efm32_adc_attr, ++}; ++ ++static int efm32_adc_probe(struct platform_device *pdev) ++{ ++ struct efm32_adc_ddata *ddata; ++ struct resource *res; ++ int ret; ++ ++ ddata = kzalloc(sizeof(*ddata), GFP_KERNEL); ++ if (!ddata) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "failed to determine base address\n"); ++ goto err_get_base; ++ } ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret <= 0) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "failed to determine irq\n"); ++ goto err_get_irq; ++ } ++ ddata->irq = ret; ++ ++ ddata->base = ioremap(res->start, resource_size(res)); ++ if (!ddata->base) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "failed to remap\n"); ++ goto err_ioremap; ++ } ++ ++ ddata->clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(ddata->clk)) { ++ ret = PTR_ERR(ddata->clk); ++ dev_dbg(&pdev->dev, "failed to get clock\n"); ++ goto err_clk_get; ++ } ++ ++ platform_set_drvdata(pdev, ddata); ++ spin_lock_init(&ddata->lock); ++ ++ ret = sysfs_create_group(&pdev->dev.kobj, &efm32_adc_group); ++ if (ret) ++ goto err_create_group; ++ ++ ddata->hwmondev = hwmon_device_register(&pdev->dev); ++ if (IS_ERR(ddata->hwmondev)) { ++ ret = PTR_ERR(ddata->hwmondev); ++ ++ sysfs_remove_group(&pdev->dev.kobj, &efm32_adc_group); ++err_create_group: ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ clk_put(ddata->clk); ++err_clk_get: ++ ++ iounmap(ddata->base); ++err_ioremap: ++err_get_irq: ++err_get_base: ++ kfree(ddata); ++ } ++ ++ return ret; ++} ++ ++static int efm32_adc_remove(struct platform_device *pdev) ++{ ++ struct efm32_adc_ddata *ddata = platform_get_drvdata(pdev); ++ ++ hwmon_device_unregister(ddata->hwmondev); ++ sysfs_remove_group(&pdev->dev.kobj, &efm32_adc_group); ++ platform_set_drvdata(pdev, NULL); ++ clk_put(ddata->clk); ++ iounmap(ddata->base); ++ kfree(ddata); ++ ++ return 0; ++} ++ ++static const struct of_device_id efm32_adc_dt_ids[] = { ++ { ++ .compatible = "efm32,adc", ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(of, efm32_adc_dt_ids); ++ ++static struct platform_driver efm32_adc_driver = { ++ .probe = efm32_adc_probe, ++ .remove = efm32_adc_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = efm32_adc_dt_ids, ++ }, ++}; ++module_platform_driver(efm32_adc_driver); ++ ++MODULE_AUTHOR("Uwe Kleine-Koenig "); ++MODULE_DESCRIPTION("EFM32 ADC driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/patches/linux-3.9-rc1/0006-spi-new-controller-driver-for-efm32-SoCs.patch b/patches/linux-3.9-rc1/0006-spi-new-controller-driver-for-efm32-SoCs.patch new file mode 100644 index 0000000..6a0a368 --- /dev/null +++ b/patches/linux-3.9-rc1/0006-spi-new-controller-driver-for-efm32-SoCs.patch @@ -0,0 +1,509 @@ +From 97867b015c992f3d3642f9db6a7f2cd0557b51bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 23 Feb 2012 10:44:35 +0100 +Subject: [PATCH 06/18] spi: new controller driver for efm32 SoCs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +known issues: + efm32-spi efm32-spi.1: master is unqueued, this is deprecated + +Signed-off-by: Uwe Kleine-König +--- + drivers/spi/Kconfig | 5 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-efm32.c | 456 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 462 insertions(+) + create mode 100644 drivers/spi/spi-efm32.c + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index f80eee7..4db256b 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -145,6 +145,11 @@ config SPI_DAVINCI + help + SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules. + ++config SPI_EFM32 ++ tristate "EFM32 SPI controller" ++ depends on ARCH_EFM32 ++ select SPI_BITBANG ++ + config SPI_EP93XX + tristate "Cirrus Logic EP93xx SPI controller" + depends on ARCH_EP93XX +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index e53c309..e272e69 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -26,6 +26,7 @@ obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o + obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o + obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o + spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o ++obj-$(CONFIG_SPI_EFM32) += spi-efm32.o + obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o + obj-$(CONFIG_SPI_FALCON) += spi-falcon.o + obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o +diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c +new file mode 100644 +index 0000000..5964d01 +--- /dev/null ++++ b/drivers/spi/spi-efm32.c +@@ -0,0 +1,456 @@ ++/* ++ * Copyright (C) 2012 Uwe Kleine-Koenig for Pengutronix ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "efm32-spi" ++ ++#define REG_CTRL 0x00 ++#define REG_CTRL_SYNC 0x0001 ++#define REG_CTRL_CLKPOL 0x0100 ++#define REG_CTRL_CLKPHA 0x0200 ++#define REG_CTRL_MSBF 0x0400 ++#define REG_CTRL_TXBIL 0x1000 ++ ++#define REG_FRAME 0x04 ++#define REG_FRAME_DATABITS__MASK 0x000f ++#define REG_FRAME_DATABITS(n) ((n) - 3) ++ ++#define REG_CMD 0x0c ++#define REG_CMD_RXEN 0x0001 ++#define REG_CMD_RXDIS 0x0002 ++#define REG_CMD_TXEN 0x0004 ++#define REG_CMD_TXDIS 0x0008 ++#define REG_CMD_MASTEREN 0x0010 ++ ++#define REG_STATUS 0x10 ++#define REG_STATUS_TXENS 0x0002 ++#define REG_STATUS_TXC 0x0020 ++#define REG_STATUS_TXBL 0x0040 ++#define REG_STATUS_RXDATAV 0x0080 ++ ++#define REG_CLKDIV 0x14 ++ ++#define REG_RXDATAX 0x18 ++#define REG_RXDATAX_RXDATA__MASK 0x01ff ++#define REG_RXDATAX_PERR 0x4000 ++#define REG_RXDATAX_FERR 0x8000 ++ ++#define REG_TXDATA 0x34 ++ ++#define REG_IF 0x40 ++#define REG_IF_TXBL 0x0002 ++#define REG_IF_RXDATAV 0x0004 ++ ++#define REG_IFS 0x44 ++#define REG_IFC 0x48 ++#define REG_IEN 0x4c ++ ++#define REG_ROUTE 0x54 ++#define REG_ROUTE_RXPEN 0x0001 ++#define REG_ROUTE_TXPEN 0x0002 ++#define REG_ROUTE_CLKPEN 0x0008 ++#define REG_ROUTE_LOCATION__MASK 0x0700 ++#define REG_ROUTE_LOCATION(n) (((n) << 8) & REG_ROUTE_LOCATION__MASK) ++ ++ ++ ++struct efm32_spi_ddata { ++ /* bitbang must be the first member */ ++ struct spi_bitbang bitbang; ++ ++ spinlock_t lock; ++ ++ struct clk *clk; ++ void __iomem *base; ++ unsigned int rxirq, txirq; ++ ++ /* irq data */ ++ struct completion done; ++ const void *tx_buf; ++ void *rx_buf; ++ unsigned tx_len, rx_len; ++}; ++ ++static void efm32_spi_write32(struct efm32_spi_ddata *ddata, ++ u32 value, unsigned offset) ++{ ++ writel_relaxed(value, ddata->base + offset); ++} ++ ++static u32 efm32_spi_read32(struct efm32_spi_ddata *ddata, unsigned offset) ++{ ++ return readl_relaxed(ddata->base + offset); ++} ++ ++static int efm32_spi_setup(struct spi_device *spi) ++{ ++ pr_debug("%s\n", __func__); ++ ++ return 0; ++ ++} ++ ++static void efm32_spi_cleanup(struct spi_device *spi) ++{ ++ pr_debug("%s\n", __func__); ++} ++ ++static void efm32_spi_chipselect(struct spi_device *spi, int is_on) ++{ ++ int value = !(spi->mode & SPI_CS_HIGH) == !(is_on == BITBANG_CS_ACTIVE); ++ void __iomem *addr; ++ ++ /* XXX */ ++ if (!value) ++ addr = (void *)0x40006080; ++ else ++ addr = (void *)0x4000607c; ++ ++ writel(0x8, addr); ++} ++ ++static int efm32_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ++{ ++ struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master); ++ ++ unsigned bpw = t && t->bits_per_word ? ++ t->bits_per_word : spi->bits_per_word; ++ unsigned speed = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz; ++ unsigned long clkfreq = clk_get_rate(ddata->clk); ++ u32 clkdiv; ++ ++ efm32_spi_write32(ddata, REG_CTRL_SYNC | REG_CTRL_MSBF | ++ (spi->mode & SPI_CPHA ? REG_CTRL_CLKPHA : 0) | ++ (spi->mode & SPI_CPOL ? REG_CTRL_CLKPOL : 0), REG_CTRL); ++ ++ efm32_spi_write32(ddata, ++ REG_FRAME_DATABITS(bpw), REG_FRAME); ++ /* XXX */ ++ if (2 * speed >= clkfreq) ++ clkdiv = 0; ++ else ++ clkdiv = 64 * (DIV_ROUND_UP(2 * clkfreq, speed) - 4); ++ ++ if (clkdiv > (1U << 21)) ++ return -EINVAL; ++ ++ efm32_spi_write32(ddata, clkdiv, REG_CLKDIV); ++ efm32_spi_write32(ddata, REG_CMD_MASTEREN, REG_CMD); ++ efm32_spi_write32(ddata, REG_CMD_RXEN | REG_CMD_TXEN, REG_CMD); ++ ++ return 0; ++} ++ ++#define DEFINE_EFM32_SPI_XFER(type) \ ++static void efm32_spi_tx_ ## type(struct efm32_spi_ddata *ddata) \ ++{ \ ++ type val = 0; \ ++ \ ++ if (ddata->tx_len >= sizeof(type)) { \ ++ if (ddata->tx_buf) { \ ++ val = *(type *)ddata->tx_buf; \ ++ ddata->tx_buf += sizeof(type); \ ++ } \ ++ \ ++ ddata->tx_len -= sizeof(type); \ ++ efm32_spi_write32(ddata, val, REG_TXDATA); \ ++ pr_debug("%s: tx 0x%x\n", __func__, val); \ ++ } \ ++} \ ++ \ ++static void efm32_spi_rx_ ## type(struct efm32_spi_ddata *ddata) \ ++{ \ ++ if (ddata->rx_len >= sizeof(type)) { \ ++ u32 rxdata = efm32_spi_read32(ddata, REG_RXDATAX); \ ++ pr_debug("%s: rx 0x%x\n", __func__, rxdata); \ ++ \ ++ if (ddata->rx_buf) { \ ++ *(type *)ddata->rx_buf = rxdata; \ ++ ddata->rx_buf += sizeof(type); \ ++ } \ ++ \ ++ ddata->rx_len -= sizeof(type); \ ++ } \ ++} ++ ++DEFINE_EFM32_SPI_XFER(u8) ++ ++static void efm32_spi_filltx(struct efm32_spi_ddata *ddata) ++{ ++ while (ddata->tx_len && ++ ddata->tx_len + 2 /* XXX * bpw */ > ddata->rx_len && ++ efm32_spi_read32(ddata, REG_STATUS) & REG_STATUS_TXBL) { ++ efm32_spi_tx_u8(ddata); ++ } ++} ++ ++static int efm32_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ++{ ++ struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master); ++ int ret = -EBUSY; ++ ++ spin_lock_irq(&ddata->lock); ++ ++ if (ddata->tx_buf || ddata->rx_buf) ++ goto out_unlock; ++ ++ ddata->tx_buf = t->tx_buf; ++ ddata->rx_buf = t->rx_buf; ++ ddata->tx_len = ddata->rx_len = t->len; ++ ++ efm32_spi_filltx(ddata); ++ ++ init_completion(&ddata->done); ++ ++ efm32_spi_write32(ddata, REG_IF_TXBL | REG_IF_RXDATAV, REG_IEN); ++ ++ spin_unlock_irq(&ddata->lock); ++ ++ wait_for_completion(&ddata->done); ++ ++ spin_lock_irq(&ddata->lock); ++ ++ ret = t->len - max(ddata->tx_len, ddata->rx_len); ++ ++ efm32_spi_write32(ddata, 0, REG_IEN); ++ ddata->tx_buf = ddata->rx_buf = NULL; ++ ++out_unlock: ++ spin_unlock_irq(&ddata->lock); ++ ++ return ret; ++} ++ ++static irqreturn_t efm32_spi_rxirq(int irq, void *data) ++{ ++ struct efm32_spi_ddata *ddata = data; ++ irqreturn_t ret = IRQ_NONE; ++ ++ spin_lock(&ddata->lock); ++ ++ while (ddata->rx_len > 0 && ++ efm32_spi_read32(ddata, REG_STATUS) & ++ REG_STATUS_RXDATAV) { ++ efm32_spi_rx_u8(ddata); ++ ++ ret = IRQ_HANDLED; ++ } ++ ++ if (!ddata->rx_len) { ++ u32 ien = efm32_spi_read32(ddata, REG_IEN); ++ ++ ien &= ~REG_IF_RXDATAV; ++ ++ efm32_spi_write32(ddata, ien, REG_IEN); ++ ++ complete(&ddata->done); ++ } ++ ++ spin_unlock(&ddata->lock); ++ ++ return ret; ++} ++ ++static irqreturn_t efm32_spi_txirq(int irq, void *data) ++{ ++ struct efm32_spi_ddata *ddata = data; ++ ++ pr_debug("%s: txlen = %u, rxlen = %u, if=0x%08x, status=0x%08x\n", ++ __func__, ddata->tx_len, ddata->rx_len, ++ efm32_spi_read32(ddata, REG_IF), ++ efm32_spi_read32(ddata, REG_STATUS)); ++ ++ spin_lock(&ddata->lock); ++ ++ efm32_spi_filltx(ddata); ++ ++ pr_debug("%s: txlen = %u, rxlen = %u\n", __func__, ++ ddata->tx_len, ddata->rx_len); ++ ++ if (!ddata->tx_len) { ++ u32 ien = efm32_spi_read32(ddata, REG_IEN); ++ ++ ien &= ~REG_IF_TXBL; ++ ++ efm32_spi_write32(ddata, ien, REG_IEN); ++ pr_debug("disable TXBL\n"); ++ } ++ ++ spin_unlock(&ddata->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int efm32_spi_probe(struct platform_device *pdev) ++{ ++ struct efm32_spi_ddata *ddata; ++ struct resource *res; ++ int ret; ++ struct spi_master *master; ++ ++ pr_debug("%s %d\n", __func__, sizeof(struct efm32_spi_ddata)); ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*ddata)); ++ if (!master) { ++ dev_dbg(&pdev->dev, ++ "failed to allocate spi master controller\n"); ++ return -ENOMEM; ++ } ++ platform_set_drvdata(pdev, master); ++ ++ master->dev.of_node = pdev->dev.of_node; ++ ++ master->bus_num = pdev->id; ++ master->num_chipselect = 1; ++ master->setup = efm32_spi_setup; ++ master->cleanup = efm32_spi_cleanup; ++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; ++ ++ ddata = spi_master_get_devdata(master); ++ ++ ddata->bitbang.master = spi_master_get(master); ++ ddata->bitbang.chipselect = efm32_spi_chipselect; ++ ddata->bitbang.setup_transfer = efm32_spi_setup_transfer; ++ ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs; ++ ++ spin_lock_init(&ddata->lock); ++ ++ ddata->clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(ddata->clk)) { ++ ret = PTR_ERR(ddata->clk); ++ dev_dbg(&pdev->dev, "failed to get clock: %d\n", ret); ++ goto err_clk_get; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ ret = -ENODEV; ++ dev_dbg(&pdev->dev, "failed to determine base address\n"); ++ goto err_get_base; ++ } ++ ++ if (resource_size(res) < 60) { ++ ret = -EINVAL; ++ dev_dbg(&pdev->dev, "memory resource too small\n"); ++ goto err_too_small; ++ } ++ ++ /* XXX: request_mem_region? */ ++ ++ ddata->base = ioremap(res->start, resource_size(res)); ++ if (!ddata->base) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "failed to remap memory\n"); ++ goto err_ioremap; ++ } ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret <= 0) { ++ dev_dbg(&pdev->dev, "failed to get rx irq\n"); ++ goto err_get_rxirq; ++ } ++ ++ ddata->rxirq = ret; ++ ++ ret = platform_get_irq(pdev, 1); ++ if (ret <= 0) ++ ret = ddata->rxirq + 1; ++ ++ ddata->txirq = ret; ++ ++ efm32_spi_write32(ddata, 0, REG_IEN); ++ efm32_spi_write32(ddata, REG_ROUTE_TXPEN | REG_ROUTE_RXPEN | ++ REG_ROUTE_CLKPEN | REG_ROUTE_LOCATION(1), REG_ROUTE); ++ ++ ret = request_irq(ddata->rxirq, efm32_spi_rxirq, 0, DRIVER_NAME, ddata); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to register rxirq (%d)\n", ret); ++ goto err_request_rxirq; ++ } ++ ++ ret = request_irq(ddata->txirq, efm32_spi_txirq, 0, DRIVER_NAME, ddata); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to register txirq (%d)\n", ret); ++ goto err_request_txirq; ++ } ++ ++ ret = spi_bitbang_start(&ddata->bitbang); ++ if (ret) { ++ dev_dbg(&pdev->dev, "spi_bitbang_start failed: %d\n", ret); ++ ++ free_irq(ddata->txirq, ddata); ++err_request_txirq: ++ ++ free_irq(ddata->rxirq, ddata); ++err_request_rxirq: ++err_get_rxirq: ++ iounmap(ddata->base); ++err_ioremap: ++err_too_small: ++err_get_base: ++ clk_put(ddata->clk); ++err_clk_get: ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(master); ++ kfree(master); ++ } ++ ++ pr_debug("%s returns %d\n", __func__, ret); ++ return ret; ++} ++ ++static int efm32_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master = platform_get_drvdata(pdev); ++ struct efm32_spi_ddata *ddata = spi_master_get_devdata(master); ++ ++ free_irq(ddata->txirq, ddata); ++ free_irq(ddata->rxirq, ddata); ++ iounmap(ddata->base); ++ clk_put(ddata->clk); ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(master); ++ kfree(master); ++ ++ return 0; ++} ++ ++static const struct of_device_id efm32_spi_dt_ids[] = { ++ { ++ .compatible = "efm32,spi", ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids); ++ ++static struct platform_driver efm32_spi_driver = { ++ .probe = efm32_spi_probe, ++ .remove = efm32_spi_remove, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = efm32_spi_dt_ids, ++ }, ++}; ++module_platform_driver(efm32_spi_driver); ++ ++MODULE_AUTHOR("Uwe Kleine-Koenig "); ++MODULE_DESCRIPTION("EFM32 SPI driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/patches/linux-3.9-rc1/0007-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch b/patches/linux-3.9-rc1/0007-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch new file mode 100644 index 0000000..0375c70 --- /dev/null +++ b/patches/linux-3.9-rc1/0007-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch @@ -0,0 +1,773 @@ +From 99b8cd03a6661c265cde0ad53be5a408e289e6a4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 17 Nov 2011 14:36:23 +0100 +Subject: [PATCH 07/18] ARM: new platform for Energy Micro's EFM32 Cortex-M3 + SoCs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/Kconfig | 14 +- + arch/arm/Kconfig.debug | 16 ++ + arch/arm/Makefile | 1 + + arch/arm/boot/dts/efm32gg-dk3750.dts | 111 ++++++++++ + arch/arm/mach-efm32/Makefile | 1 + + arch/arm/mach-efm32/Makefile.boot | 1 + + arch/arm/mach-efm32/clk.c | 38 ++++ + arch/arm/mach-efm32/cmu.h | 11 + + arch/arm/mach-efm32/common.h | 1 + + arch/arm/mach-efm32/dtmachine.c | 28 +++ + arch/arm/mach-efm32/include/mach/debug-macro.S | 48 ++++ + arch/arm/mach-efm32/include/mach/entry-macro.S | 9 + + arch/arm/mach-efm32/include/mach/io.h | 6 + + arch/arm/mach-efm32/include/mach/irqs.h | 6 + + arch/arm/mach-efm32/include/mach/system.h | 18 ++ + arch/arm/mach-efm32/include/mach/timex.h | 7 + + arch/arm/mach-efm32/time.c | 289 +++++++++++++++++++++++++ + 17 files changed, 604 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/efm32gg-dk3750.dts + create mode 100644 arch/arm/mach-efm32/Makefile + create mode 100644 arch/arm/mach-efm32/Makefile.boot + create mode 100644 arch/arm/mach-efm32/clk.c + create mode 100644 arch/arm/mach-efm32/cmu.h + create mode 100644 arch/arm/mach-efm32/common.h + create mode 100644 arch/arm/mach-efm32/dtmachine.c + create mode 100644 arch/arm/mach-efm32/include/mach/debug-macro.S + create mode 100644 arch/arm/mach-efm32/include/mach/entry-macro.S + create mode 100644 arch/arm/mach-efm32/include/mach/io.h + create mode 100644 arch/arm/mach-efm32/include/mach/irqs.h + create mode 100644 arch/arm/mach-efm32/include/mach/system.h + create mode 100644 arch/arm/mach-efm32/include/mach/timex.h + create mode 100644 arch/arm/mach-efm32/time.c + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 7c8c607..37ed23d 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -444,6 +444,18 @@ config ARCH_EBSA110 + Ethernet interface, two PCMCIA sockets, two serial ports and a + parallel port. + ++config ARCH_EFM32 ++ bool "Energy Micro Cortex M3 Platform" ++ depends on !MMU ++ select ARM_NVIC ++ select CLKSRC_MMIO ++ select CPU_V7M ++ select GENERIC_CLOCKEVENTS ++ select HAVE_CLK ++ select NO_DMA ++ select NO_IOPORT ++ select USE_OF ++ + config ARCH_EP93XX + bool "EP93xx-based" + select ARCH_HAS_HOLES_MEMORYMODEL +@@ -1813,7 +1825,7 @@ config FORCE_MAX_ZONEORDER + int "Maximum zone order" if ARCH_SHMOBILE + range 11 64 if ARCH_SHMOBILE + default "12" if SOC_AM33XX +- default "9" if SA1111 ++ default "9" if SA1111 || ARCH_EFM32 + default "11" + help + The kernel memory allocator divides physically contiguous memory +diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug +index acdddda..b49c0f8 100644 +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -156,6 +156,22 @@ choice + Say Y here if you want the debug print routines to direct + their output to the serial port in the DC21285 (Footbridge). + ++ config DEBUG_EFM32_USART1 ++ bool "Kernel low-level debugging messages via USART1" ++ depends on ARCH_EFM32 ++ help ++ Say Y here if you want the debug print routines to direct ++ their output to the second USART port on efm32 based ++ machines. ++ ++ config DEBUG_EFM32_UART1 ++ bool "Kernel low-level debugging messages via UART1" ++ depends on ARCH_EFM32 ++ help ++ Say Y here if you want the debug print routines to direct ++ their output to the second UART port on efm32 based ++ machines. ++ + config DEBUG_FOOTBRIDGE_COM1 + bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1" + depends on FOOTBRIDGE +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index f11b8da..13134dc 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -146,6 +146,7 @@ machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx + machine-$(CONFIG_ARCH_DAVINCI) += davinci + machine-$(CONFIG_ARCH_DOVE) += dove + machine-$(CONFIG_ARCH_EBSA110) += ebsa110 ++machine-$(CONFIG_ARCH_EFM32) += efm32 + machine-$(CONFIG_ARCH_EP93XX) += ep93xx + machine-$(CONFIG_ARCH_GEMINI) += gemini + machine-$(CONFIG_ARCH_H720X) += h720x +diff --git a/arch/arm/boot/dts/efm32gg-dk3750.dts b/arch/arm/boot/dts/efm32gg-dk3750.dts +new file mode 100644 +index 0000000..ae0a59a +--- /dev/null ++++ b/arch/arm/boot/dts/efm32gg-dk3750.dts +@@ -0,0 +1,111 @@ ++/dts-v1/; ++/include/ "skeleton.dtsi" ++ ++/ { ++ model = "Energy Micro Giant Gecko Development Kit"; ++ compatible = "efm32,dk3750"; ++ ++ aliases { ++ serial4 = &uart4; ++ }; ++ ++ nvic: nv-interrupt-controller@0xe0000000 { ++ compatible = "arm,armv7m-nvic"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ reg = <0xe000e100 0xc00>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyefm4,115200 init=/linuxrc ignore_loglevel ihash_entries=64 dhash_entries=64 earlyprintk uclinux.physaddr=0x8c400000 root=/dev/mtdblock0"; ++ }; ++ ++ memory { ++ reg = <0x88000000 0x400000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&nvic>; ++ ranges; ++ ++ adc@0x40002000 { ++ compatible = "efm32,adc"; ++ reg = <0x40002000 0x400>; ++ interrupts = <7>; ++ status = "ok"; ++ }; ++ ++ gpio: gpio@0x40006000 { ++ compatible = "efm32,gpio"; ++ reg = <0x40006000 0x1000>; ++ interrupts = <1 11>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "ok"; ++ }; ++ ++ spi@0x4000c400 { /* USART1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "efm32,spi"; ++ reg = <0x4000c400 0x400>; ++ interrupts = <15>; ++ status = "ok"; ++ ++ ks8851@0 { ++ compatible = "ks8851"; ++ spi-max-frequency = <6000000>; ++ reg = <0>; ++ interrupt-parent = <&boardfpga>; ++ interrupts = <4>; ++ status = "ok"; ++ }; ++ }; ++ ++ uart4: uart@0x4000e400 { /* UART1 */ ++ compatible = "efm32,uart"; ++ reg = <0x4000e400 0x400>; ++ interrupts = <22>; ++ location = <2>; ++ status = "ok"; ++ }; ++ ++ timer0: timer@40010000 { ++ compatible = "efm32,timer"; ++ reg = <0x40010000 0x400>; ++ interrupts = <2>; ++ }; ++ ++ timer1: timer@40010400 { ++ compatible = "efm32,timer"; ++ reg = <0x40010400 0x400>; ++ interrupts = <12>; ++ }; ++ ++ timer2: timer@40010800 { ++ compatible = "efm32,timer"; ++ reg = <0x40010800 0x400>; ++ interrupts = <13>; ++ }; ++ ++ timer3: timer@40010c00 { ++ compatible = "efm32,timer"; ++ reg = <0x40010c00 0x400>; ++ interrupts = <14>; ++ }; ++ ++ boardfpga: boardfpga@0x80000000 { ++ compatible = "efm32board"; ++ reg = <0x80000000 0x400>; ++ irq-gpios = <&gpio 64 1>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "ok"; ++ }; ++ }; ++}; +diff --git a/arch/arm/mach-efm32/Makefile b/arch/arm/mach-efm32/Makefile +new file mode 100644 +index 0000000..c6786a0 +--- /dev/null ++++ b/arch/arm/mach-efm32/Makefile +@@ -0,0 +1 @@ ++obj-y += clk.o dtmachine.o time.o +diff --git a/arch/arm/mach-efm32/Makefile.boot b/arch/arm/mach-efm32/Makefile.boot +new file mode 100644 +index 0000000..385e93a +--- /dev/null ++++ b/arch/arm/mach-efm32/Makefile.boot +@@ -0,0 +1 @@ ++dtb-$(CONFIG_MACH_EFM32GG_DK3750) += efm32gg-dk3750.dtb +diff --git a/arch/arm/mach-efm32/clk.c b/arch/arm/mach-efm32/clk.c +new file mode 100644 +index 0000000..5b158ab +--- /dev/null ++++ b/arch/arm/mach-efm32/clk.c +@@ -0,0 +1,38 @@ ++#include ++#include ++#include ++ ++#include "cmu.h" ++ ++struct clk *clk_get(struct device *dev, const char *id) ++{ ++ return NULL; ++} ++EXPORT_SYMBOL(clk_get); ++ ++int clk_enable(struct clk *clk) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(clk_enable); ++ ++void clk_disable(struct clk *clk) ++{ ++} ++EXPORT_SYMBOL(clk_disable); ++ ++unsigned long clk_get_rate(struct clk *clk) ++{ ++ u32 cmu_status = __raw_readl(CMU_STATUS); ++ ++ if (cmu_status & CMU_STATUS_HFRCOSEL) ++ return 14000000; ++ else ++ return 48000000; ++} ++EXPORT_SYMBOL(clk_get_rate); ++ ++void clk_put(struct clk *clk) ++{ ++} ++EXPORT_SYMBOL(clk_put); +diff --git a/arch/arm/mach-efm32/cmu.h b/arch/arm/mach-efm32/cmu.h +new file mode 100644 +index 0000000..05ef676 +--- /dev/null ++++ b/arch/arm/mach-efm32/cmu.h +@@ -0,0 +1,11 @@ ++#include "common.h" ++ ++#define CMU_OSCENCMD IOMEM(0x400c8020) ++#define CMU_OSCENCMD_HFXOEN 0x00000004 ++ ++#define CMU_CMD IOMEM(0x400C8024) ++#define CMU_CMD_HFCLKSEL_HFXO 0x00000002 ++ ++#define CMU_STATUS IOMEM(0x400c802c) ++#define CMU_STATUS_HFRCOSEL 0x00000400 ++#define CMU_STATUS_HFXOSEL 0x00000800 +diff --git a/arch/arm/mach-efm32/common.h b/arch/arm/mach-efm32/common.h +new file mode 100644 +index 0000000..e8ce15e +--- /dev/null ++++ b/arch/arm/mach-efm32/common.h +@@ -0,0 +1 @@ ++void efm32_timer_init(void); +diff --git a/arch/arm/mach-efm32/dtmachine.c b/arch/arm/mach-efm32/dtmachine.c +new file mode 100644 +index 0000000..30fce6d +--- /dev/null ++++ b/arch/arm/mach-efm32/dtmachine.c +@@ -0,0 +1,28 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++ ++static void __init efm32_init(void) ++{ ++ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); ++} ++ ++static const char *const efm32gg_compat[] __initconst = { ++ "efm32,dk3750", ++ NULL ++}; ++ ++DT_MACHINE_START(EFM32DT, "EFM32 (Device Tree Support)") ++ .init_irq = irqchip_init, ++ .init_time = efm32_timer_init, ++ .init_machine = efm32_init, ++ .dt_compat = efm32gg_compat, ++MACHINE_END +diff --git a/arch/arm/mach-efm32/include/mach/debug-macro.S b/arch/arm/mach-efm32/include/mach/debug-macro.S +new file mode 100644 +index 0000000..c58915c +--- /dev/null ++++ b/arch/arm/mach-efm32/include/mach/debug-macro.S +@@ -0,0 +1,48 @@ ++/* ++ * 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. ++ */ ++ ++#define UARTn_CMD 0x000c ++#define UARTn_CMD_TXEN 0x0004 ++ ++#define UARTn_STATUS 0x0010 ++#define UARTn_STATUS_TXC 0x0020 ++#define UARTn_STATUS_TXBL 0x0040 ++ ++#define UARTn_TXDATA 0x0034 ++ ++ .macro addruart, rx, tmp ++#if defined(CONFIG_DEBUG_EFM32_USART1) ++ ldr \rx, =(0x4000c400) /* USART1 */ ++#elif defined(CONFIG_DEBUG_EFM32_UART1) ++ ldr \rx, =(0x4000e400) /* UART1 */ ++#else ++#error "No debug port configured" ++#endif ++ /* ++ * enable TX. The driver might disable that to save energy. We ++ * don't care about disabling at the end as during debug power ++ * consumption isn't that important. ++ */ ++ ldr \tmp, =(UARTn_CMD_TXEN) ++ str \tmp, [\rx, #UARTn_CMD] ++ .endm ++ ++ ++ .macro senduart,rd,rx ++ strb \rd, [\rx, #UARTn_TXDATA] ++ .endm ++ ++ .macro waituart,rd,rx ++1001: ldr \rd, [\rx, #UARTn_STATUS] ++ tst \rd, #UARTn_STATUS_TXBL ++ beq 1001b ++ .endm ++ ++ .macro busyuart,rd,rx ++1001: ldr \rd, [\rx, UARTn_STATUS] ++ tst \rd, #UARTn_STATUS_TXC ++ bne 1001b ++ .endm +diff --git a/arch/arm/mach-efm32/include/mach/entry-macro.S b/arch/arm/mach-efm32/include/mach/entry-macro.S +new file mode 100644 +index 0000000..547f7b1 +--- /dev/null ++++ b/arch/arm/mach-efm32/include/mach/entry-macro.S +@@ -0,0 +1,9 @@ ++/* ++ * ++ */ ++ ++ .macro get_irqnr_preamble, base, tmp ++ .endm ++ ++ .macro arch_ret_to_user, tmp1, tmp2 ++ .endm +diff --git a/arch/arm/mach-efm32/include/mach/io.h b/arch/arm/mach-efm32/include/mach/io.h +new file mode 100644 +index 0000000..bc3519b +--- /dev/null ++++ b/arch/arm/mach-efm32/include/mach/io.h +@@ -0,0 +1,6 @@ ++#ifndef __MACH_IO_H__ ++#define __MACH_IO_H__ ++ ++#define __mem_pci(a) (a) ++ ++#endif /* __MACH_IO_H__ */ +diff --git a/arch/arm/mach-efm32/include/mach/irqs.h b/arch/arm/mach-efm32/include/mach/irqs.h +new file mode 100644 +index 0000000..e33ed12 +--- /dev/null ++++ b/arch/arm/mach-efm32/include/mach/irqs.h +@@ -0,0 +1,6 @@ ++#ifndef __MACH_IRQS_H__ ++#define __MACH_IRQS_H__ ++ ++#define NR_IRQS 82 ++ ++#endif /* __MACH_IRQS_H__ */ +diff --git a/arch/arm/mach-efm32/include/mach/system.h b/arch/arm/mach-efm32/include/mach/system.h +new file mode 100644 +index 0000000..619222c +--- /dev/null ++++ b/arch/arm/mach-efm32/include/mach/system.h +@@ -0,0 +1,18 @@ ++#ifndef __MACH_SYSTEM_H__ ++#define __MACH_SYSTEM_H__ ++ ++#include ++ ++static inline void arch_idle(void) ++{ ++ cpu_do_idle(); ++} ++ ++static inline void arch_reset(char mode, const char *cmd) ++{ ++ /* XXX: move this to (say) cpuv7m_reset */ ++ dsb(); ++ __raw_writel(0x05fa0004, (void __iomem *)0xe000ed0c); ++ dsb(); ++} ++#endif /* __MACH_SYSTEM_H__ */ +diff --git a/arch/arm/mach-efm32/include/mach/timex.h b/arch/arm/mach-efm32/include/mach/timex.h +new file mode 100644 +index 0000000..b408dce +--- /dev/null ++++ b/arch/arm/mach-efm32/include/mach/timex.h +@@ -0,0 +1,7 @@ ++#ifndef __MACH_TIMEX_H__ ++#define __MACH_TIMEX_H__ ++ ++/* just a bogus value */ ++#define CLOCK_TICK_RATE 12345678 ++ ++#endif /* __MACH_TIMEX_H__ */ +diff --git a/arch/arm/mach-efm32/time.c b/arch/arm/mach-efm32/time.c +new file mode 100644 +index 0000000..e0ac6ea +--- /dev/null ++++ b/arch/arm/mach-efm32/time.c +@@ -0,0 +1,289 @@ ++#define DEBUG ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++ ++#define BASEADDR_TIMER(n) IOMEM(0x40010000 + (n) * 0x400) ++ ++#define TIMERn_CTRL 0x00 ++#define TIMERn_CTRL_PRESC(val) (((val) & 0xf) << 24) ++#define TIMERn_CTRL_PRESC_1024 TIMERn_CTRL_PRESC(10) ++#define TIMERn_CTRL_CLKSEL(val) (((val) & 0x3) << 16) ++#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK TIMERn_CTRL_CLKSEL(0) ++#define TIMERn_CTRL_OSMEN 0x00000010 ++#define TIMERn_CTRL_MODE(val) (((val) & 0x3) << 0) ++#define TIMERn_CTRL_MODE_UP TIMERn_CTRL_MODE(0) ++#define TIMERn_CTRL_MODE_DOWN TIMERn_CTRL_MODE(1) ++ ++#define TIMERn_CMD 0x04 ++#define TIMERn_CMD_START 0x1 ++#define TIMERn_CMD_STOP 0x2 ++ ++#define TIMERn_IEN 0x0c ++#define TIMERn_IF 0x10 ++#define TIMERn_IFS 0x14 ++#define TIMERn_IFC 0x18 ++#define TIMERn_IRQ_UF 0x2 ++#define TIMERn_IRQ_OF 0x1 ++ ++#define TIMERn_TOP 0x1c ++#define TIMERn_CNT 0x24 ++ ++#define TIMER_CLOCKSOURCE 0 ++#define TIMER_CLOCKEVENT 1 ++ ++struct efm32_clock_event_ddata { ++ struct clock_event_device evtdev; ++ void __iomem *base; ++}; ++ ++static void efm32_clock_event_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evtdev) ++{ ++ struct efm32_clock_event_ddata *ddata = ++ container_of(evtdev, struct efm32_clock_event_ddata, evtdev); ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); ++ writel_relaxed(137 /* XXX: magic constant */, ddata->base + TIMERn_TOP); ++ writel_relaxed(TIMERn_CTRL_PRESC_1024 | ++ TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | ++ TIMERn_CTRL_MODE_DOWN, ++ ddata->base + TIMERn_CTRL); ++ writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); ++ break; ++ ++ case CLOCK_EVT_MODE_ONESHOT: ++ writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); ++ writel_relaxed(TIMERn_CTRL_PRESC_1024 | ++ TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | ++ TIMERn_CTRL_OSMEN | ++ TIMERn_CTRL_MODE_DOWN, ++ ddata->base + TIMERn_CTRL); ++ break; ++ ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); ++ break; ++ ++ case CLOCK_EVT_MODE_RESUME: ++ break; ++ } ++} ++ ++static int efm32_clock_event_set_next_event(unsigned long evt, ++ struct clock_event_device *evtdev) ++{ ++ struct efm32_clock_event_ddata *ddata = ++ container_of(evtdev, struct efm32_clock_event_ddata, evtdev); ++ ++ writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); ++ writel_relaxed(evt, ddata->base + TIMERn_CNT); ++ writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); ++ ++ return 0; ++} ++ ++static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) ++{ ++ struct efm32_clock_event_ddata *ddata = dev_id; ++ ++ writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); ++ ++ ddata->evtdev.event_handler(&ddata->evtdev); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct efm32_clock_event_ddata clock_event_ddata = { ++ .evtdev = { ++ .name = "efm32 clockevent", ++ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_MODE_PERIODIC, ++ .set_mode = efm32_clock_event_set_mode, ++ .set_next_event = efm32_clock_event_set_next_event, ++ .rating = 200, ++ }, ++}; ++ ++static struct irqaction efm32_clock_event_irq = { ++ .name = "efm32 clockevent", ++ .flags = IRQF_TIMER, ++ .handler = efm32_clock_event_handler, ++ .dev_id = &clock_event_ddata, ++}; ++ ++/* ++ * XXX: use clk_ API to get frequency and enabling of the clocks used. ++ * Here the reset defaults are used: ++ * - freq_{HFPERCLK} = freq_{HFCLK} ++ * (CMU_HFPERCLKDIV_HFPERCLKDIV = 0x0) ++ * - freq_{HFCLK} = freq_{HFRCO} ++ * (CMU_CTRL_HFCLKDIV = 0x0, CMU_STATUS_HFRCOSEL = 0x1) ++ * - freq_{HFRCO} = 14MHz ++ * (CMU_HFRCOCTRL_BAND = 0x3) ++ * ++ * So the HFPERCLK runs at 14MHz. The timer has an additional prescaler ++ * programmed to /1024. This make the timer run at ++ * ++ * 14 MHz / 1024 = 13671.875 Hz ++ * ++ * When HFXO is used HFPERCLK runs at 48 MHz, so the timer runs at ++ * ++ * 48 MHz / 1024 = 46875 Hz ++ * ++ */ ++ ++#define of_clk_get(np, i) NULL ++ ++static int efm32_timer_clocksource_init(struct device_node *np) ++{ ++ struct clk *clk; ++ void __iomem *base; ++ unsigned long rate; ++ int ret; ++ ++ clk = of_clk_get(np, 0); ++ if (IS_ERR(clk)) { ++ pr_err("failed to get clock for clocksource\n"); ++ ret = PTR_ERR(clk); ++ goto err_clk_get; ++ } ++ ++ ret = clk_prepare_enable(clk); ++ if (ret) { ++ pr_err("failed to enable timer clock for clocksource\n"); ++ goto err_clk_enable; ++ } ++ rate = clk_get_rate(clk); ++ ++ base = of_iomap(np, 0); ++ if (!base) { ++ pr_err("failed to map registers for clocksource\n"); ++ goto err_iomap; ++ } ++ ++ writel_relaxed(TIMERn_CTRL_PRESC_1024 | ++ TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | ++ TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); ++ writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); ++ ++ return clocksource_mmio_init(base + TIMERn_CNT, ++ "efm32 timer", rate / 1024, 200, 16, ++ clocksource_mmio_readl_up); ++ ++ iounmap(base); ++err_iomap: ++ ++ clk_disable_unprepare(clk); ++err_clk_enable: ++ ++ clk_put(clk); ++err_clk_get: ++ ++ return ret; ++} ++ ++int __init efm32_clockevent_init(struct device_node *np) ++{ ++ struct clk *clk; ++ void __iomem *base; ++ unsigned long rate; ++ int irq; ++ int ret; ++ ++ clk = of_clk_get(np, 0); ++ if (IS_ERR(clk)) { ++ pr_err("failed to get clock for clocksource\n"); ++ ret = PTR_ERR(clk); ++ goto err_clk_get; ++ } ++ ++ ret = clk_prepare_enable(clk); ++ if (ret) { ++ pr_err("failed to enable timer clock for clocksource\n"); ++ goto err_clk_enable; ++ } ++ rate = clk_get_rate(clk); ++ ++ base = of_iomap(np, 0); ++ if (!base) { ++ pr_err("failed to map registers for clocksource\n"); ++ goto err_iomap; ++ } ++ ++ irq = irq_of_parse_and_map(np, 0); ++ if (!irq) { ++ pr_err("failed to get irq\n"); ++ goto err_get_irq; ++ } ++ ++ writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); ++ ++ clock_event_ddata.base = base; ++ ++ setup_irq(irq, &efm32_clock_event_irq); ++ ++ /* XXX: tune min_delta */ ++ clockevents_config_and_register(&clock_event_ddata.evtdev, ++ rate / 1024, 0xf, 0xffff); ++ ++ return 0; ++ ++err_get_irq: ++ ++ iounmap(base); ++err_iomap: ++ ++ clk_disable_unprepare(clk); ++err_clk_enable: ++ ++ clk_put(clk); ++err_clk_get: ++ ++ return ret; ++} ++ ++void __init efm32_timer_init(void) ++{ ++ struct device_node *np; ++ ++ /* ++ * enable CMU_HFPERCLKEN0_TIMERn for clocksource via bit-band; ++ * XXX: drop this when clock framework is not a stub anymore. ++ */ ++ __raw_writel(1, IOMEM(0x43900894 + 4 * TIMER_CLOCKSOURCE)); ++ /* enable CMU_HFPERCLKEN0_TIMERn for clockevent via bit-band */ ++ __raw_writel(1, IOMEM(0x43900894 + 4 * TIMER_CLOCKEVENT)); ++ ++ np = of_find_compatible_node(NULL, NULL, "efm32,timer"); ++ if (!np) { ++ pr_err("failed to find timer node for clocksource\n"); ++ return; ++ } ++ ++ efm32_timer_clocksource_init(np); ++ ++ np = of_find_compatible_node(np, NULL, "efm32,timer"); ++ if (!np) { ++ pr_err("failed to find timer node for clock events\n"); ++ return; ++ } ++ ++ efm32_clockevent_init(np); ++ ++ of_node_put(np); ++} diff --git a/patches/linux-3.9-rc1/0008-ARM-efm32-some-more-stuff.patch b/patches/linux-3.9-rc1/0008-ARM-efm32-some-more-stuff.patch new file mode 100644 index 0000000..8bb474e --- /dev/null +++ b/patches/linux-3.9-rc1/0008-ARM-efm32-some-more-stuff.patch @@ -0,0 +1,296 @@ +From e290629da5b121e255abaa78388a50935d3ac344 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Tue, 12 Mar 2013 14:44:10 +0100 +Subject: [PATCH 08/18] ARM: efm32: some more stuff +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/Kconfig-nommu | 4 + + arch/arm/mach-efm32/Makefile | 2 +- + arch/arm/mach-efm32/common.c | 207 ++++++++++++++++++++++++++++++++++++++++ + arch/arm/mach-efm32/common.h | 7 ++ + arch/arm/mach-efm32/dtmachine.c | 7 ++ + 5 files changed, 226 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/mach-efm32/common.c + +diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu +index c859495..fcbb5c4 100644 +--- a/arch/arm/Kconfig-nommu ++++ b/arch/arm/Kconfig-nommu +@@ -11,18 +11,22 @@ config SET_MEM_PARAM + + config DRAM_BASE + hex '(S)DRAM Base Address' if SET_MEM_PARAM ++ default 0x88000000 if MACH_EFM32GG_DK3750 + default 0x00800000 + + config DRAM_SIZE + hex '(S)DRAM SIZE' if SET_MEM_PARAM ++ default 0x00400000 if MACH_EFM32GG_DK3750 + default 0x00800000 + + config FLASH_MEM_BASE + hex 'FLASH Base Address' if SET_MEM_PARAM ++ default 0x00000000 if MACH_EFM32GG_DK3750 + default 0x00400000 + + config FLASH_SIZE + hex 'FLASH Size' if SET_MEM_PARAM ++ default 0x00100000 if MACH_EFM32GG_DK3750 + default 0x00400000 + + config PROCESSOR_ID +diff --git a/arch/arm/mach-efm32/Makefile b/arch/arm/mach-efm32/Makefile +index c6786a0..d70b093 100644 +--- a/arch/arm/mach-efm32/Makefile ++++ b/arch/arm/mach-efm32/Makefile +@@ -1 +1 @@ +-obj-y += clk.o dtmachine.o time.o ++obj-y += clk.o common.o dtmachine.o time.o +diff --git a/arch/arm/mach-efm32/common.c b/arch/arm/mach-efm32/common.c +new file mode 100644 +index 0000000..cb073ba +--- /dev/null ++++ b/arch/arm/mach-efm32/common.c +@@ -0,0 +1,207 @@ ++/* ++ * Copyright (C) 2012 Uwe Kleine-Koenig for Pengutronix ++ * ++ * 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 ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++ ++/* move this somewhere else */ ++void cm3_restart(char mode, const char *cmd) ++{ ++ dsb(); ++ __raw_writel(0x05fa0004, (void __iomem *)0xe000ed0c); ++ dsb(); ++} ++ ++#define MEM_INFO_FLASH (void __iomem *)0x0fe081f8 ++#define MEM_INFO_RAM (void __iomem *)0x0fe081fa ++#define PART_NUMBER (void __iomem *)0x0fe081fc ++#define PART_FAMILY (void __iomem *)0x0fe081fe ++#define PROD_REV (void __iomem *)0x0fe081ff ++ ++static const struct efm32_family_mapping { ++ u8 id; ++ const char *name; ++ const char *abbrev; ++} efm32_family_mapping[] __initconst = { ++ { ++ .id = 71, ++ .name = "Gecko", ++ .abbrev = "G", ++ }, { ++ .id = 72, ++ .name = "Giant Gecko", ++ .abbrev = "GG", ++ }, { ++ .id = 73, ++ .name = "Tiny Gecko", ++ .abbrev = "TG", ++ }, { ++ .id = 74, ++ .name = "Leopard Gecko", ++ .abbrev = "LG", ++ }, { ++ .id = 75, ++ .name = "Zero Gecko", ++ .abbrev = "ZG", ++ }, ++}; ++ ++static const char *__init efm32_get_familyname(u8 id) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(efm32_family_mapping) && ++ efm32_family_mapping[i].id <= id; ++i) { ++ if (efm32_family_mapping[i].id == id) ++ return efm32_family_mapping[i].name; ++ } ++ ++ return "unknown"; ++} ++ ++static const char *__init efm32_get_familyabbrev(u8 id) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(efm32_family_mapping) && ++ efm32_family_mapping[i].id <= id; ++i) { ++ if (efm32_family_mapping[i].id == id) ++ return efm32_family_mapping[i].abbrev; ++ } ++ ++ return "unknown"; ++} ++ ++static char revbuf[4] __initdata = ""; ++static volatile const u32 * const romtable = (void *)0xe00fffe0; ++ ++static const char *__init efm32_get_rev(void) ++{ ++ if (revbuf[0] == '\0') { ++ u32 major = romtable[0] & 0x3f; ++ u32 minor = (romtable[2] & 0xf0) | ((romtable[3] >> 4) & 0x0f); ++ ++ if (minor < 25) ++ sprintf(revbuf, "%u%c", major, 'A' + minor); ++ else { ++ revbuf[0] = '?'; ++ revbuf[1] = '\0'; ++ } ++ } ++ return revbuf; ++} ++ ++void __init efm32_print_cpuinfo(void) ++{ ++ u16 partno = __raw_readw(PART_NUMBER); ++ u8 family = __raw_readb(PART_FAMILY); ++ u8 rev = __raw_readb(PROD_REV); ++ u16 flashsize = __raw_readw(MEM_INFO_FLASH); ++ u16 raminfo = __raw_readw(MEM_INFO_RAM); ++ ++ pr_info("Energy Micro %s, EFM32%s%hdF%hd (rev %s, prodrev %hhd), %hd kB RAM\n", ++ efm32_get_familyname(family), ++ efm32_get_familyabbrev(family), partno, ++ flashsize, efm32_get_rev(), rev, raminfo); ++} ++ ++static const struct { ++ u32 value; ++ u32 mask; ++ const char *cause; ++} efm32_reset_causes[] = { ++ { ++ .value = 0x0001, ++ .mask = 0x0001, ++ .cause = "A Power-on Reset has been performed", ++ }, { ++ .value = 0x0002, ++ .mask = 0x0083, ++ .cause = "A Brown-out has been detected on the unregulated power", ++ }, { ++ .value = 0x0004, ++ .mask = 0x001f, ++ .cause = "A Brown-out has been detected on the regulated power", ++ }, { ++ .value = 0x0008, ++ .mask = 0x000b, ++ .cause = "An external reset has been applied", ++ }, { ++ .value = 0x0010, ++ .mask = 0x0013, ++ .cause = "A watchdog reset has occurred", ++ }, { ++ .value = 0x0020, ++ .mask = 0x07ff, ++ .cause = "A lockup reset has occurred", ++ }, { ++ .value = 0x0080, ++ .mask = 0x07df, ++ .cause = "A system request reset has occurred", ++ }, { ++ .value = 0x0080, ++ .mask = 0x0799, ++ .cause = "The system as woken up from EM4", ++ }, { ++ .value = 0x0180, ++ .mask = 0x799, ++ .cause = "The system as woken up from EM4 on an EM4 wakeup reset request from pin", ++ }, { ++ .value = 0x0200, ++ .mask = 0x079f, ++ .cause = "A Brown-out has been detected on Analog Power Domain 0 (AVDD0)", ++ }, { ++ .value = 0x0400, ++ .mask = 0x079f, ++ .cause = "A Brown-out has been detected on Analog Power Domain 1 (AVDD1)", ++ }, { ++ .value = 0x0800, ++ .mask = 0x0800, ++ .cause = "A Brown-out has been detected by the Backup BOD on VDD_DREG", ++ }, { ++ .value = 0x1000, ++ .mask = 0x1000, ++ .cause = "A Brown-out has been detected by the Backup BOD on BU_VIN", ++ }, { ++ .value = 0x2000, ++ .mask = 0x2000, ++ .cause = "A Brown-out has been detected by the Backup BOD on unregulated power", ++ }, { ++ .value= 0x4000, ++ .mask = 0x4000, ++ .cause = "A Brown-out has been detected by the Backup BOD on regulated power", ++ }, { ++ .value = 0x8000, ++ .mask = 0x8000, ++ .cause = "The system has been in Backup mode", ++ }, ++}; ++ ++void __init efm32_print_reset_cause(void) ++{ ++ u32 rmu_rstcause = __raw_readl((void __iomem *)0x400ca004); ++ int i; ++ ++ pr_info("Reset Cause: 0x%08x\n", rmu_rstcause); ++ ++ for (i = 0; i < ARRAY_SIZE(efm32_reset_causes); ++i) { ++ if ((rmu_rstcause & efm32_reset_causes[i].mask) == ++ efm32_reset_causes[i].value) ++ pr_info(" `-> %s.\n", efm32_reset_causes[i].cause); ++ } ++ ++ /* clear RMU_RSTCAUSE */ ++ __raw_writel(1, (void __iomem *)0x400ca008); ++ __raw_writel(1, (void __iomem *)0x400c6024); ++ __raw_writel(0, (void __iomem *)0x400c6024); ++} +diff --git a/arch/arm/mach-efm32/common.h b/arch/arm/mach-efm32/common.h +index e8ce15e..0d2efb9 100644 +--- a/arch/arm/mach-efm32/common.h ++++ b/arch/arm/mach-efm32/common.h +@@ -1 +1,8 @@ + void efm32_timer_init(void); ++ ++/* XXX: find a better place for that */ ++void cm3_restart(char mode, const char *cmd); ++ ++void efm32_print_cpuinfo(void); ++ ++void efm32_print_reset_cause(void); +diff --git a/arch/arm/mach-efm32/dtmachine.c b/arch/arm/mach-efm32/dtmachine.c +index 30fce6d..edad4c4 100644 +--- a/arch/arm/mach-efm32/dtmachine.c ++++ b/arch/arm/mach-efm32/dtmachine.c +@@ -13,6 +13,13 @@ + static void __init efm32_init(void) + { + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); ++ ++ /* ++ * Pinmuxing isn't specified in the device tree. Probably it's too heavy ++ * considering that there is only 4 MiB of RAM ++ */ ++ //efm32gg990_add_efm32_pinctrl(); ++ //pinmux_register_mappings(efm32_pinmux, ARRAY_SIZE(efm32_pinmux)); + } + + static const char *const efm32gg_compat[] __initconst = { diff --git a/patches/linux-3.9-rc1/0009-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch b/patches/linux-3.9-rc1/0009-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch new file mode 100644 index 0000000..6403f33 --- /dev/null +++ b/patches/linux-3.9-rc1/0009-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch @@ -0,0 +1,387 @@ +From f4340e563b61d024c5364c6612574e4693cde848 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Tue, 12 Feb 2013 23:31:27 +0100 +Subject: [PATCH 09/18] gpio: new driver for Energy Micro's GPIO component + +--- + arch/arm/Kconfig | 1 + + drivers/gpio/Kconfig | 4 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-efm32.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 335 insertions(+) + create mode 100644 drivers/gpio/gpio-efm32.c + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 37ed23d..8ead415 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -447,6 +447,7 @@ config ARCH_EBSA110 + config ARCH_EFM32 + bool "Energy Micro Cortex M3 Platform" + depends on !MMU ++ select ARCH_REQUIRE_GPIOLIB + select ARM_NVIC + select CLKSRC_MMIO + select CPU_V7M +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index 93aaadf..d51f4af 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -125,6 +125,10 @@ config GPIO_IT8761E + help + Say yes here to support GPIO functionality of IT8761E super I/O chip. + ++config GPIO_EFM32 ++ tristate "Energy Micro EFM32 GPIO support" ++ depends on ARCH_EFM32 ++ + config GPIO_EM + tristate "Emma Mobile GPIO" + depends on ARM +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index 22e07bc..3cbabb9 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o + obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o + obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o + obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o ++obj-$(CONFIG_GPIO_EFM32) += gpio-efm32.o + obj-$(CONFIG_GPIO_EM) += gpio-em.o + obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o + obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o +diff --git a/drivers/gpio/gpio-efm32.c b/drivers/gpio/gpio-efm32.c +new file mode 100644 +index 0000000..648a154 +--- /dev/null ++++ b/drivers/gpio/gpio-efm32.c +@@ -0,0 +1,329 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define DRIVER_NAME "efm32-gpio" ++ ++#define GPIO_Px_MODEL(p) (0x024 * (p) + 0x004) ++#define GPIO_Px_MODEH(p) (0x024 * (p) + 0x008) ++#define GPIO_Px_DOUT(p) (0x024 * (p) + 0x00c) ++#define GPIO_Px_DOUTSET(p) (0x024 * (p) + 0x010) ++#define GPIO_Px_DOUTCLR(p) (0x024 * (p) + 0x014) ++#define GPIO_Px_DIN(p) (0x024 * (p) + 0x01c) ++#define GPIO_EXTIPSELL 0x100 ++#define GPIO_EXTIPSELH 0x104 ++#define GPIO_IEN 0x110 ++#define GPIO_IF 0x114 ++#define GPIO_IFC 0x11c ++ ++struct efm32_gpio_ddata { ++ void __iomem *base; ++ spinlock_t lock; ++ unsigned int irq_even, irq_odd; ++ struct irq_domain *irq_domain; ++ struct gpio_chip chip; ++ unsigned assigned_irqpins; ++}; ++ ++#define to_ddata(chip) container_of(chip, struct efm32_gpio_ddata, chip) ++ ++static unsigned efm32_gpio_get_mode(struct efm32_gpio_ddata *ddata, ++ unsigned pin, unsigned port) ++{ ++ return (readl(ddata->base + (pin < 8 ? GPIO_Px_MODEL(port) : GPIO_Px_MODEH(port))) >> (4 * (pin & 7))) & 0xf; ++ ++} ++static int efm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ unsigned mode = efm32_gpio_get_mode(ddata, pin, port); ++ ++ /* ++ * XXX: don't reconfigure, needs to be resolved in combination with a ++ * pinmux driver ++ */ ++ if (mode > 0 && mode < 4) ++ return 0; ++ else ++ return -EIO; ++} ++ ++static int efm32_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ ++ /* XXX use bitband to simplify? */ ++ return readl(ddata->base + GPIO_Px_DIN(port)) & (1 << pin); ++} ++ ++static int efm32_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ unsigned mode = efm32_gpio_get_mode(ddata, pin, port); ++ ++ /* ++ * XXX: don't reconfigure, needs to be resolved in combination with a ++ * pinmux driver ++ */ ++ if (mode >= 4) ++ return 0; ++ else ++ return -EIO; ++} ++ ++static void efm32_gpio_set(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ ++ writel(1 << pin, ddata->base + ++ (value ? GPIO_Px_DOUTSET(port) : GPIO_Px_DOUTCLR(port))); ++} ++ ++static int efm32_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ unsigned extipsel_offset = pin < 8 ? GPIO_EXTIPSELL : GPIO_EXTIPSELH; ++ unsigned extipsel; ++ unsigned extipsel_shift = (pin % 8) * 4; ++ ++ spin_lock(&ddata->lock); ++ ++ extipsel = readl(ddata->base + extipsel_offset); ++ ++ if (ddata->assigned_irqpins & (1 << pin)) { ++ if (((extipsel >> extipsel_shift) & 0x7) != port) { ++ spin_unlock(&ddata->lock); ++ return -EBUSY; ++ } ++ } ++ ++ extipsel &= ~(0x7 << extipsel_shift); ++ extipsel |= port << extipsel_shift; ++ ddata->assigned_irqpins |= 1 << pin; ++ writel(extipsel, ddata->base + extipsel_offset); ++ ++ spin_unlock(&ddata->lock); ++ ++ return irq_create_mapping(ddata->irq_domain, offset % 16); ++} ++ ++static irqreturn_t efm32_gpio_handler(struct efm32_gpio_ddata *ddata, unsigned mask) ++{ ++ unsigned flag, init_flag; ++ irqreturn_t ret = IRQ_NONE; ++ ++ init_flag = flag = readl(ddata->base + GPIO_IF) & mask; ++ ++ while (flag) { ++ int line = __fls(flag); ++ ++ writel(1 << line, ddata->base + GPIO_IFC); ++ if (generic_handle_irq(irq_create_mapping(ddata->irq_domain, line))) ++ ret = IRQ_HANDLED; ++ ++ flag &= ~(1 << line); ++ } ++ return ret; ++} ++ ++static irqreturn_t efm32_gpio_handler_even(int irq, void *data) ++{ ++ struct efm32_gpio_ddata *ddata = data; ++ return efm32_gpio_handler(ddata, 0x55555555U); ++} ++ ++static irqreturn_t efm32_gpio_handler_odd(int irq, void *data) ++{ ++ struct efm32_gpio_ddata *ddata = data; ++ return efm32_gpio_handler(ddata, 0xaaaaaaaaU); ++} ++ ++static void efm32_gpio_irq_ack(struct irq_data *data) ++{ ++ struct efm32_gpio_ddata *ddata = irq_get_chip_data(data->irq); ++ writel(1 << data->hwirq, ddata->base + GPIO_IFC); ++} ++ ++static void efm32_gpio_irq_mask(struct irq_data *data) ++{ ++ struct efm32_gpio_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned ien; ++ ++ spin_lock(&ddata->lock); ++ ien = readl(ddata->base + GPIO_IEN); ++ ien &= ~(1 << data->hwirq); ++ writel(ien, ddata->base + GPIO_IEN); ++ spin_unlock(&ddata->lock); ++} ++ ++static void efm32_gpio_irq_unmask(struct irq_data *data) ++{ ++ struct efm32_gpio_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned ien; ++ ++ spin_lock(&ddata->lock); ++ ien = readl(ddata->base + GPIO_IEN); ++ ien |= 1 << data->hwirq; ++ writel(ien, ddata->base + GPIO_IEN); ++ spin_unlock(&ddata->lock); ++} ++ ++static struct irq_chip efm32_gpio_irqchip = { ++ .irq_ack = efm32_gpio_irq_ack, ++ .irq_mask = efm32_gpio_irq_mask, ++ .irq_unmask = efm32_gpio_irq_unmask, ++}; ++ ++static int efm32_gpio_irq_map(struct irq_domain *d, unsigned int virq, ++ irq_hw_number_t hw) ++{ ++ struct efm32_gpio_ddata *ddata = d->host_data; ++ ++ irq_set_chip_data(virq, ddata); ++ irq_set_chip_and_handler(virq, &efm32_gpio_irqchip, handle_edge_irq); ++ ++ set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops efm32_gpio_irq_domain_ops = { ++ .map = efm32_gpio_irq_map, ++}; ++ ++static int efm32_gpio_probe(struct platform_device *pdev) ++{ ++ struct efm32_gpio_ddata *ddata; ++ struct resource *res; ++ int ret = -ENOMEM; ++ int irq_even, irq_odd; ++ ++ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); ++ if (!ddata) { ++ dev_err(&pdev->dev, "cannot allocate driver data"); ++ return -ENOMEM; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't get device resources\n"); ++ return -ENOENT; ++ } ++ ++ irq_even = platform_get_irq(pdev, 0); ++ irq_odd = platform_get_irq(pdev, 1); ++ if (irq_even <= 0 || irq_odd <= 0) { ++ dev_err(&pdev->dev, "can't get irq numbers (%d, %d)\n", ++ irq_even, irq_odd); ++ return -ENOENT; ++ } ++ ddata->irq_even = irq_even; ++ ddata->irq_odd = irq_odd; ++ ++ ddata->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!ddata->base) { ++ dev_err(&pdev->dev, ++ "cannot request and ioremap register set\n"); ++ return -EADDRNOTAVAIL; ++ } ++ ++ spin_lock_init(&ddata->lock); ++ ++ /* disable and clear irqs */ ++ writel(0, ddata->base + GPIO_IEN); ++ writel(0xffff, ddata->base + GPIO_IFC); ++ ++ ddata->irq_domain = irq_domain_add_linear(pdev->dev.of_node, ++ 16, &efm32_gpio_irq_domain_ops, ddata); ++ if (!ddata->irq_domain) { ++ dev_err(&pdev->dev, "failed to add irq_domain\n"); ++ goto err_add_irq_domain; ++ } ++ ++ ddata->chip.label = DRIVER_NAME; ++ ddata->chip.dev = &pdev->dev; ++ ddata->chip.owner = THIS_MODULE; ++ ++ //ddata->chip.get_direction ++ ddata->chip.direction_input = efm32_gpio_direction_input; ++ ddata->chip.get = efm32_gpio_get; ++ ddata->chip.direction_output = efm32_gpio_direction_output; ++ ddata->chip.set = efm32_gpio_set; ++ ddata->chip.to_irq = efm32_gpio_to_irq; ++ ddata->chip.base = -1; ++ ddata->chip.ngpio = 96; ++ ddata->chip.can_sleep = 0; ++ ++ ret = request_irq(ddata->irq_even, efm32_gpio_handler_even, ++ 0, DRIVER_NAME, ddata); ++ if (ret) ++ goto err_request_even_irq; ++ ++ ret = request_irq(ddata->irq_odd, efm32_gpio_handler_odd, ++ 0, DRIVER_NAME, ddata); ++ if (ret) ++ goto err_request_odd_irq; ++ ++ ret = gpiochip_add(&ddata->chip); ++ if (ret) { ++ free_irq(ddata->irq_odd, ddata); ++err_request_odd_irq: ++ ++ free_irq(ddata->irq_even, ddata); ++err_request_even_irq: ++ ++ irq_domain_remove(ddata->irq_domain); ++ } ++ ++err_add_irq_domain: ++ return ret; ++} ++ ++static const struct of_device_id efm32_gpio_dt_ids[] = { ++ { ++ .compatible = "efm32,gpio", ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(of, efm32_gpio_dt_ids); ++ ++static struct platform_driver efm32_gpio_driver = { ++ .probe = efm32_gpio_probe, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = efm32_gpio_dt_ids, ++ }, ++}; ++ ++static int __init efm32_gpio_init(void) ++{ ++ return platform_driver_register(&efm32_gpio_driver); ++} ++postcore_initcall(efm32_gpio_init); ++ ++MODULE_LICENSE("GPL v2"); diff --git a/patches/linux-3.9-rc1/0010-efm-board-controller-driver.patch b/patches/linux-3.9-rc1/0010-efm-board-controller-driver.patch new file mode 100644 index 0000000..adddd13 --- /dev/null +++ b/patches/linux-3.9-rc1/0010-efm-board-controller-driver.patch @@ -0,0 +1,235 @@ +From 9e2433894ee2579cf10a16b596eb4fc20e2171e0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 7 Feb 2013 09:45:30 +0100 +Subject: [PATCH 10/18] efm board controller driver + +--- + drivers/mfd/Kconfig | 5 ++ + drivers/mfd/Makefile | 1 + + drivers/mfd/efm32board.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 198 insertions(+) + create mode 100644 drivers/mfd/efm32board.c + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 671f5b1..80c49f0 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -1118,6 +1118,11 @@ config MFD_AS3711 + help + Support for the AS3711 PMIC from AMS + ++config MFD_EFM32BOARD ++ tristate "efm32 board" ++ depends on ARM ++ select MFD_CORE ++ + endmenu + endif + +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index b90409c..373a6de 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -148,3 +148,4 @@ obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o + obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o + obj-$(CONFIG_MFD_RETU) += retu-mfd.o + obj-$(CONFIG_MFD_AS3711) += as3711.o ++obj-$(CONFIG_MFD_EFM32BOARD) += efm32board.o +diff --git a/drivers/mfd/efm32board.c b/drivers/mfd/efm32board.c +new file mode 100644 +index 0000000..5c74a16 +--- /dev/null ++++ b/drivers/mfd/efm32board.c +@@ -0,0 +1,192 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "efm32board" ++ ++#define MAGIC 0x04 ++#define INTFLAG 0x40 ++#define INTEN 0x42 ++ ++struct efm32board_ddata { ++ void __iomem *base; ++ unsigned int irq; ++ struct irq_chip chip; ++ struct irq_domain *domain; ++}; ++ ++static void efm32board_irq_ack(struct irq_data *data) ++{ ++ struct efm32board_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned short val; ++ ++ /* XXX: locking */ ++ val = readw(ddata->base + INTFLAG); ++ val &= ~(1 << data->hwirq); ++ writew(val, ddata->base + INTFLAG); ++} ++ ++static void efm32board_irq_mask(struct irq_data *data) ++{ ++ struct efm32board_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned short val; ++ ++ if (data->hwirq != 2) { ++ /* XXX: locking */ ++ val = readw(ddata->base + INTEN); ++ val &= ~(1 << data->hwirq); ++ writew(val, ddata->base + INTEN); ++ } ++} ++ ++static void efm32board_irq_unmask(struct irq_data *data) ++{ ++ struct efm32board_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned short val; ++ ++ /* XXX: locking */ ++ val = readw(ddata->base + INTEN); ++ val |= 1 << data->hwirq; ++ writew(val, ddata->base + INTEN); ++} ++ ++static irqreturn_t efm32board_handler(int irq, void *data) ++{ ++ unsigned short val; ++ struct efm32board_ddata *ddata = data; ++ irqreturn_t ret = IRQ_NONE; ++ ++ val = readw(ddata->base + INTFLAG); ++ /* ack BC irq */ ++ writew(0, ddata->base + INTFLAG); ++ ++ while (val) { ++ int line = __fls(val); ++ ++ if (!generic_handle_irq(irq_create_mapping(ddata->domain, line))) ++ ret = IRQ_HANDLED; ++ val &= ~(1 << line); ++ } ++ return ret; ++} ++ ++int efm32board_irqdomain_map(struct irq_domain *d, unsigned int virq, ++ irq_hw_number_t hw) ++{ ++ struct efm32board_ddata *ddata = d->host_data; ++ ++ irq_set_chip_data(virq, ddata); ++ irq_set_chip_and_handler(virq, &ddata->chip, handle_edge_irq); ++ ++ set_irq_flags(virq, IRQF_VALID); ++ ++ return 0; ++} ++ ++const struct irq_domain_ops efm32board_irqdomain_ops = { ++ .map = efm32board_irqdomain_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++static int efm32board_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int irq, gpio, ret; ++ struct efm32board_ddata *ddata; ++ unsigned short val; ++ ++ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); ++ if (!ddata) { ++ dev_err(&pdev->dev, "cannot allocate driver data"); ++ return -ENOMEM; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't get device resources\n"); ++ return -ENOENT; ++ } ++ ++ gpio = of_get_named_gpio_flags(pdev->dev.of_node, "irq-gpios", 0, NULL); ++ if (gpio < 0) { ++ dev_err(&pdev->dev, "can't get irq gpio\n"); ++ return gpio; ++ } ++ ++ ret = gpio_request(gpio, DRIVER_NAME); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot request irq gpio\n"); ++ return ret; ++ } ++ ++ ret = gpio_direction_input(gpio); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot configure irq gpio as input\n"); ++ return ret; ++ } ++ ++ irq = gpio_to_irq(gpio); ++ if (irq <= 0) { ++ dev_err(&pdev->dev, "can't get irq number\n"); ++ return irq < 0 ? irq : -ENOENT; ++ } ++ ddata->irq = irq; ++ ++ ddata->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!ddata->base) { ++ dev_err(&pdev->dev, "cannot request and ioremap register set\n"); ++ return -EADDRNOTAVAIL; ++ } ++ ++ val = readw(ddata->base + MAGIC); ++ if (val != 0xef32) { ++ dev_err(&pdev->dev, "Magic not found (0x%hx)\n", val); ++ return -ENODEV; ++ } ++ ++ /* disable and clear all irqs */ ++ writew(0, ddata->base + INTEN); ++ writew(0, ddata->base + INTFLAG); ++ ++ /* XXX: enable joystick irq */ ++ writew(4, ddata->base + INTEN); ++ ++ ddata->chip.name = DRIVER_NAME; ++ ddata->chip.irq_ack = efm32board_irq_ack; ++ ddata->chip.irq_mask = efm32board_irq_mask; ++ ddata->chip.irq_unmask = efm32board_irq_unmask; ++ ++ ret = request_irq(irq, efm32board_handler, 0, DRIVER_NAME, ddata); ++ if (ret) ++ goto err_request_irq; ++ ++ ddata->domain = irq_domain_add_simple(pdev->dev.of_node, 5, 0, ++ &efm32board_irqdomain_ops, ddata); ++ if (!ddata->domain) { ++ ret = -ENOMEM; ++ dev_err(&pdev->dev, "cannot create irq domain\n"); ++ ++ free_irq(irq, ddata); ++ } ++err_request_irq: ++ return ret; ++} ++ ++static const struct of_device_id efm32board_dt_ids[] = { ++ { .compatible = "efm32board", }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver efm32board_driver = { ++ .probe = efm32board_probe, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = efm32board_dt_ids, ++ }, ++}; ++module_platform_driver(efm32board_driver); diff --git a/patches/linux-3.9-rc1/0011-ARM-v7m-add-trivial-suspend-support.patch b/patches/linux-3.9-rc1/0011-ARM-v7m-add-trivial-suspend-support.patch new file mode 100644 index 0000000..53eb90a --- /dev/null +++ b/patches/linux-3.9-rc1/0011-ARM-v7m-add-trivial-suspend-support.patch @@ -0,0 +1,96 @@ +From 98001c3a7af00d8089f20549aa8877547a7cb393 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Wed, 1 Feb 2012 10:00:00 +0100 +Subject: [PATCH 11/18] ARM: v7m: add trivial suspend support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/Kconfig | 2 +- + arch/arm/kernel/suspend.c | 10 +++++++++- + arch/arm/mm/proc-v7m.S | 13 +++++++++++++ + 3 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 8ead415..ddf1cb0 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -2341,7 +2341,7 @@ source "kernel/power/Kconfig" + config ARCH_SUSPEND_POSSIBLE + depends on !ARCH_S5PC100 + depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \ +- CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK ++ CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK || CPU_V7M + def_bool y + + config ARM_CPU_SUSPEND +diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c +index 358bca3..bc451f6 100644 +--- a/arch/arm/kernel/suspend.c ++++ b/arch/arm/kernel/suspend.c +@@ -22,7 +22,11 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) + *save_ptr = virt_to_phys(ptr); + + /* This must correspond to the LDM in cpu_resume() assembly */ ++#ifdef CONFIG_MMU + *ptr++ = virt_to_phys(idmap_pgd); ++#else ++ *ptr++ = 0; ++#endif + *ptr++ = sp; + *ptr++ = virt_to_phys(cpu_do_resume); + +@@ -53,11 +57,13 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) + */ + int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) + { +- struct mm_struct *mm = current->active_mm; + int ret; ++#ifdef CONFIG_MMU ++ struct mm_struct *mm = current->active_mm; + + if (!idmap_pgd) + return -EINVAL; ++#endif + + /* + * Provide a temporary page table with an identity mapping for +@@ -66,10 +72,12 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) + * back to the correct page tables. + */ + ret = __cpu_suspend(arg, fn); ++#ifdef CONFIG_MMU + if (ret == 0) { + cpu_switch_mm(mm->pgd, mm); + local_flush_tlb_all(); + } ++#endif + + return ret; + } +diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S +index c2b68d3..433b99f 100644 +--- a/arch/arm/mm/proc-v7m.S ++++ b/arch/arm/mm/proc-v7m.S +@@ -59,6 +59,19 @@ ENTRY(cpu_v7m_switch_mm) + mov pc, lr + ENDPROC(cpu_v7m_switch_mm) + ++.globl cpu_v7m_suspend_size ++.equ cpu_v7m_suspend_size, 0 ++ ++#ifdef CONFIG_ARM_CPU_SUSPEND ++ENTRY(cpu_v7m_do_suspend) ++ mov pc, lr ++ENDPROC(cpu_v7m_do_suspend) ++ ++ENTRY(cpu_v7m_do_resume) ++ mov pc, lr ++ENDPROC(cpu_v7m_do_resume) ++#endif ++ + cpu_v7m_name: + .ascii "ARMv7-M Processor" + .align diff --git a/patches/linux-3.9-rc1/0012-ARM-efm32-add-trivial-suspend-support.patch b/patches/linux-3.9-rc1/0012-ARM-efm32-add-trivial-suspend-support.patch new file mode 100644 index 0000000..f6b5017 --- /dev/null +++ b/patches/linux-3.9-rc1/0012-ARM-efm32-add-trivial-suspend-support.patch @@ -0,0 +1,75 @@ +From 2bc45209b9eccc7c08864b371e2fb38419c2bdc2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Wed, 1 Feb 2012 10:00:21 +0100 +Subject: [PATCH 12/18] ARM: efm32: add trivial suspend support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/mach-efm32/Makefile | 2 ++ + arch/arm/mach-efm32/pm.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + create mode 100644 arch/arm/mach-efm32/pm.c + +diff --git a/arch/arm/mach-efm32/Makefile b/arch/arm/mach-efm32/Makefile +index d70b093..a7f1102 100644 +--- a/arch/arm/mach-efm32/Makefile ++++ b/arch/arm/mach-efm32/Makefile +@@ -1 +1,3 @@ + obj-y += clk.o common.o dtmachine.o time.o ++ ++obj-$(CONFIG_PM) += pm.o +diff --git a/arch/arm/mach-efm32/pm.c b/arch/arm/mach-efm32/pm.c +new file mode 100644 +index 0000000..4c80906 +--- /dev/null ++++ b/arch/arm/mach-efm32/pm.c +@@ -0,0 +1,46 @@ ++#include ++#include ++ ++#include ++#include ++ ++#include "cmu.h" ++ ++static int efm32_suspend_enter(suspend_state_t state) ++{ ++ u32 cmu_status = readl(CMU_STATUS); ++ ++ /* ++ * setting SLEEPDEEP makes the efm32 enter EM2 or EM3 (iff both ++ * LFACLK and LFBCLK are off). ++ */ ++ writel(V7M_SCS_SCR_SLEEPDEEP, V7M_SCS_SCR); ++ ++ cpu_do_idle(); ++ ++ writel(0, V7M_SCS_SCR); ++ ++ /* ++ * deep sleep disables the HF oscilator, reenable it if it was on ++ * before. ++ */ ++ if (cmu_status & CMU_STATUS_HFXOSEL) { ++ writel(CMU_OSCENCMD_HFXOEN, CMU_OSCENCMD); ++ writel(CMU_CMD_HFCLKSEL_HFXO, CMU_CMD); ++ } ++ ++ return 0; ++} ++ ++static const struct platform_suspend_ops efm32_suspend_ops = { ++ .valid = suspend_valid_only_mem, ++ .enter = efm32_suspend_enter, ++}; ++ ++static int __init efm32_pm_init(void) ++{ ++ suspend_set_ops(&efm32_suspend_ops); ++ ++ return 0; ++} ++arch_initcall(efm32_pm_init); diff --git a/patches/linux-3.9-rc1/0013-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch b/patches/linux-3.9-rc1/0013-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch new file mode 100644 index 0000000..26713be --- /dev/null +++ b/patches/linux-3.9-rc1/0013-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch @@ -0,0 +1,307 @@ +From 6340ff97fbd5394dd0c7570baebc2c3b19cec065 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Sun, 30 Oct 2011 21:11:05 +0100 +Subject: [PATCH 13/18] HACK! ARM: allow a bootloader to be embedded and do it + on efm32 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/kernel/vmlinux.lds.S | 5 + + arch/arm/mach-efm32/Makefile | 8 ++ + arch/arm/mach-efm32/bootloader.S | 252 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 265 insertions(+) + create mode 100644 arch/arm/mach-efm32/bootloader.S + +diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S +index b571484..57d266a 100644 +--- a/arch/arm/kernel/vmlinux.lds.S ++++ b/arch/arm/kernel/vmlinux.lds.S +@@ -90,6 +90,11 @@ SECTIONS + #else + . = PAGE_OFFSET + TEXT_OFFSET; + #endif ++ ++ .bootloader : { ++ *(.bootloader) ++ } ++ + .head.text : { + _text = .; + HEAD_TEXT +diff --git a/arch/arm/mach-efm32/Makefile b/arch/arm/mach-efm32/Makefile +index a7f1102..1cb3179 100644 +--- a/arch/arm/mach-efm32/Makefile ++++ b/arch/arm/mach-efm32/Makefile +@@ -1,3 +1,11 @@ ++ifeq ($(CONFIG_FLASH_MEM_BASE),0x00000000) ++obj-y += bootloader.o ++endif ++ ++ifeq ($(CONFIG_USE_OF),y) ++$(obj)/bootloader.o: $(obj)/../boot/dts/efm32gg-dk3750.dtb ++endif ++ + obj-y += clk.o common.o dtmachine.o time.o + + obj-$(CONFIG_PM) += pm.o +diff --git a/arch/arm/mach-efm32/bootloader.S b/arch/arm/mach-efm32/bootloader.S +new file mode 100644 +index 0000000..d4dbf0b +--- /dev/null ++++ b/arch/arm/mach-efm32/bootloader.S +@@ -0,0 +1,252 @@ ++#if defined(CONFIG_OF) ++#define EFM32_USE_OF ++#endif ++#define EFM32_DT_IN_SRAM ++ ++/* UART1 */ ++#define UARTBASE 0x4000e400 ++#define UARTLOCATION 2 ++ ++ .thumb ++ ++ .section ".bootloader","ax" ++ ++ /* M3 Vector table */ ++ .int 0x10001000 @ Initial SP value ++ .int reset + 1 @ Reset ++ ++reset: ++ /* init external RAM, serial port, EBI and stuff */ ++ adr r0, reginit ++1: ++ ldr r1, [r0] ++ ldr r2, [r0, #4] ++ str r2, [r1] ++ add r0, #8 ++ cmp r0, #(reginit_end) ++ blo 1b ++ ++ ++ /* init some BC registers */ ++ adr r0, bcinit ++1: ++ ldrh r1, [r0] ++ ldrh r2, [r0, #2] ++ add r1, r1, #0x80000000 ++ strh r2, [r1] ++ add r0, #4 ++ cmp r0, #(bcinit_end) ++ blo 1b ++ ++ /* give mux some time to enable the level shifter */ ++ ldr r0, =0x4000 ++1: subs r0, r0, #1 ++ bne 1b ++ ++ ldr r0, =(UARTBASE + 0x34) ++ mov r1, 0x55 ++ str r1, [r0] ++ ++ /* Zero PSRAM */ ++ ldr r0, =(0x88000000) ++ ldr r1, =(0x88400000) ++ mov r2, #0 ++ mov r3, #0 ++ mov r4, #0 ++ mov r5, #0 ++1: stmia r0!, {r2-r5} ++ cmp r0, r1 ++ bcc 1b ++ ++ /* assert zeroing succeeded */ ++ ldr r6, =(UARTBASE + 0x34) ++ mov r7, #'<' ++ str r7, [r6] ++ mov r7, #'*' ++ ldr r0, =(0x88000000) ++1: ldmia r0!, {r2-r5} ++ orr r2, r3 ++ orr r4, r5 ++ orr r2, r4 ++ cmp r2, #0 ++ it ne ++ strne r7, [r6] ++ cmp r0, r1 ++ bcc 1b ++ mov r7, #'>' ++ str r7, [r6] ++ ++#if defined(EFM32_USE_OF) && defined(EFM32_DT_IN_SRAM) ++#define dtbaddr 0x10000000 ++ ldr r0, =(dtbaddr) ++ ldr r1, =(dtb) ++ adr r2, dtbend ++ subs r2, r2, r1 ++ bl _memcpy ++#endif ++ /* detect machine type; easy we know this is an efm32gg_dk3750 */ ++ movw r0, #0 ++ movw r1, #0xf11 @ machid for efm32gg_dk3750 ++#ifdef EFM32_USE_OF ++#ifdef EFM32_DT_IN_SRAM ++ ldr r2, =(dtbaddr) ++#else ++ adr r2, dtb ++#endif ++#else ++ adr r2, ataglist ++#endif ++ movw r3, #0 ++ movw r4, #0 ++ movw r5, #0 ++ movw r6, #0 ++ movw r7, #0 ++ ++ b stext ++ ++#ifdef EFM32_DT_IN_SRAM ++_memcpy: ++ @ copies r2 bytes from r1 to r0 with r2 > 0 ++1: ++ ldrb r3, [r1], #1 ++ strb r3, [r0], #1 ++ subs r2, #1 ++ bhi 1b ++ bx lr ++#endif ++ ++ .ltorg ++ ++ .align 3 ++ /* register value pairs to initialize the machine */ ++ .type reginit, %object ++reginit: ++ /* clocks */ ++ .int 0x400C8020, 0x00000004 @ CMU_OSCENCMD |= HFXOEN ++ ++ .int 0x400c8008, 0x00000100 @ CMU_HFPERCLKDIV, reset default ++ .int 0x43900814, 0x00000001 @ CMU_HFCORECLKEN0 |= EBI via bitband ++ .int 0x439008b4, 0x00000001 @ CMU_HFPERCLKEN0 |= GPIO via bitband ++ .int 0x43900884, 0x00000001 @ CMU_HFPERCLKEN0 |= USART1 via bitband ++ .int 0x43900890, 0x00000001 @ CMU_HFPERCLKEN0 |= UART1 via bitband ++ ++ /* XXX */ ++ .int 0x439008c0, 0x00000001 @ CMU_HFPERCLKEN0 |= ADC via bitband ++ ++ /* pinmuxing */ ++ .int 0x40006000, 0x00000000 @ GPIO_PA_CTRL, reset default ++ .int 0x40006014, 0x0000807f @ GPIO_PA_DOUTCLR; EBI AD8..15 set dataout to 0 ++ .int 0x40006004, 0x04444444 @ GPIO_PA_MODEL; EBI AD9..15 set mode=pushpull ++ .int 0x40006008, 0x40000000 @ GPIO_PA_MODEH; EBI AD8 set mode=pushpull ++ .int 0x40006024, 0x00000000 @ GPIO_PB_CTRL, reset default ++ .int 0x40006038, 0x00008000 @ GPIO_PB_DOUTCLR; EBI mode on PB15 MCU_EBI_CONNECT (0) ++ .int 0x40006038, 0x0000007f @ GPIO_PB_DOUTCLR; EBI A16-22 ++ .int 0x40006028, 0x04444444 @ GPIO_PB_MODEL; EBI A16-22 ++ .int 0x40006034, 0x00000200 @ GPIO_PB_DOUTSET; set UART_TX to avoid false start ++ .int 0x4000602c, 0x40000140 @ GPIO_PB_MODEH; MCU_EBI_CONNECT -> output, UART_TX, UART_RX ++ ++ .int 0x40006048, 0x00000000 @ GPIO_PC_CTRL, reset default ++ .int 0x4000605c, 0x00000001 @ GPIO_PC_DOUTCLR; PC11 (EBI_ALE) ++ .int 0x40006050, 0x00004000 @ GPIO_PC_MODEH; PC11: Push-pull output ++ .int 0x4000606c, 0x00000000 @ GPIO_PD_CTRL, reset default ++ .int 0x4000607c, 0x00003e08 @ GPIO_PD_DOUTSET, EBI CS0-3, spiconnect set dataout to 1; ETH_SPI_#CS (D3) ++ .int 0x40006080, 0x00000007 @ GPIO_PD_DOUTCLR, ETH_SPI_{TX, RX, CLK} ++ .int 0x40006070, 0x00004414 @ GPIO_PD_MODEL; ETH_SPI_ ++ .int 0x40006074, 0x00444440 @ GPIO_PD_MODEH; EBI CS0-3, spiconnect set mode=pushpull ++ .int 0x40006090, 0x00000000 @ GPIO_PE_CTRL, reset default ++ .int 0x400060a0, 0x00000001 @ GPIO_PE_DOUTSET; FPGA irq line ++ .int 0x400060a4, 0x0000ff00 @ GPIO_PE_DOUTCLR; EBI AD0..7 set dataout to 0 ++ .int 0x40006094, 0x00000002 @ GPIO_PE_MODEL; FPGA irq line set mode=inputpull ++ .int 0x40006098, 0x44444444 @ GPIO_PE_MODEH; EBI AD0..7 set mode=pushpull ++ ++ .int 0x400060b4, 0x00000000 @ GPIO_PF_CTRL, reset default ++ .int 0x400060c8, 0x000003c0 @ GPIO_PF_DOUTCLR; EBI Wen+Ren set dataout to 0 ++ .int 0x400060b8, 0x44000000 @ GPIO_PF_MODEL; EBI Byte Lane 0 support BL0/BL1 ++ .int 0x400060bc, 0x00000044 @ GPIO_PF_MODEH; EBI WEN, REN ++ ++ .int 0x40006100, 0x00000004 @ GPIO_EXTIPSELL: select port E for irq 0 ++ .int 0x4000610c, 0x00000001 @ GPIO_EXTIFALL: trigger for falling FPGA irq line ++ .int 0x4000611c, 0x0000ffff @ ? GPIO_IFC: clear all irqs ++ .int 0x40006110, 0x00000001 @ GPIO_IEN: enable irq 0 ++ ++ /* EBI */ ++ .int 0x40008000, 0x4f00d051 @ EBI_CTRL, enable ITS, mode0=mode2=mode3=D16A16ALE, bl0-3, noidle[023] ++ /* EBI PSRAM */ ++ .int 0x40008028, 0x10000000 @ EBI_ADDRTIMING2; HALFALE ++ .int 0x4000802c, 0x20000400 @ EBI_RDTIMING2; Prefetch, StrobeCycles = 4, HoldCycles = SetupCycles = 0 ++ .int 0x40008030, 0x00000200 @ EBI_WRTIMING2; StrobeCycles = 2, HoldCycles = SetupCycles = 0 ++ .int 0x40008034, 0x00000008 @ EBI_POLARITY2, ARDY_, ALE, WE_, RE_, CS_, BL_ ++ ++ /* Board Control FPGA */ ++ .int 0x40008004, 0x10000303 @ EBI_ADDRTIMING; HALFALE, HoldCycles = SetupCycles = 3 ++ .int 0x40008008, 0x00030703 @ EBI_RDTIMING; StrobeCycles = 7, HoldCycles = SetupCycles = 3 ++ .int 0x4000800c, 0x00030703 @ EBI_WRTIMING; StrobeCycles = 7, HoldCycles = SetupCycles = 3 ++ .int 0x40008010, 0x00000008 @ EBI_POLARITY, ARDY_, ALE, WE_, RE_, CS_, BL_ ++ ++ /* external NOR flash */ ++ .int 0x40008038, 0x10000000 @ EBI_ADDRTIMING3; HALFALE, HoldCycles = SetupCycles = 0 ++ .int 0x4000803c, 0x00000700 @ EBI_RDTIMING3; StrobeCycles = 7, HoldCycles = SetupCycles = 0 ++ .int 0x40008040, 0x00000200 @ EBI_WRTIMING3; StrobeCycles = 2, HoldCycles = SetupCycles =0 ++ .int 0x40008044, 0x00000008 @ EBI_POLARITY3, ARDY_, ALE, WE_, RE_, CS_, BL_ ++ ++ .int 0x40008014, 0x105e00bb @ EBI_ROUTE ++ .int 0x40008000, 0x4f00dd51 @ EBI_CTRL, enable ITS, mode0=mode2=mode3=D16A16ALE, bl0-3, noidle[023], bank[023]en ++ ++ .int UARTBASE + 0x00, 0x00000000 @ UART1_CTRL ++ .int UARTBASE + 0x04, 0x00001005 @ UART1_FRAME ++ .int UARTBASE + 0x14, 0x00001900 @ UART1_CLKDIV ++ .int UARTBASE + 0x0c, 0x00000c04 @ UART1_CMD ++ .int UARTBASE + 0x54, 0x00000003 + (UARTLOCATION << 8) @ UART1_ROUTE ++ .int 0x400c8024, 0x00000002 @ CMU_CMD = HFCLKSEL_HFXO ++ ++reginit_end: ++ .size reginit, . - reginit ++ ++ .align 3 ++ /* register value pairs to initialize the board controller */ ++ .type bcinit, %object ++bcinit: ++ .short 0x0018, 0x1300 @ enable UART mux and ETH ++ .short 0x0014, 0x0001 @ / ++ .short 0x001a, 0x0001 @ ETH ++ ++bcinit_end: ++ .size bcinit, . - bcinit ++ ++ .align 3 ++#ifdef EFM32_USE_OF ++ .type dtb, %object ++dtb: ++ .incbin "arch/arm/boot/dts/efm32gg-dk3750.dtb" ++dtbend: ++ .size dtb, . - dtb ++ .align 3 ++ ++#else /* ifdef CONFIG_OF */ ++ ++ .type ataglist, %object ++ataglist: ++ /* ATAG_CORE */ ++ .int 0x00000005 /* .size */ ++ .int 0x54410001 /* .tag = ATAG_CORE */ ++ .int 0x00000001 /* .flags */ ++ .int 0x00001000 /* .pagesize */ ++ .int 0x000000ff /* .rootdev */ ++ /* ATAG_MEM */ ++ .int 0x00000004 /* .size */ ++ .int 0x54410002 /* .tag = ATAG_MEM */ ++ .int 0x00400000 /* .size = 4 MiB */ ++ .int 0x88000000 /* .start = SRAM_BASE */ ++ /* ATAG_CMDLINE */ ++cmdline: ++ .int (cmdline_end - cmdline) >> 2 /* .size */ ++ .int 0x54410009 /* .tag = ATAG_CMDLINE */ ++ .asciz "console=ttyefm4,115200 ignore_loglevel ihash_entries=64 dhash_entries=64 rootfstype=romfs init=/linuxrc uclinux.physaddr=0x8c000000 root=/dev/mtdblock0 earlyprintk" ++ .align 2, 0 ++cmdline_end: ++ /* ATAG_NONE */ ++ .int 0x00000000 /* .size */ ++ .int 0x00000000 /* .tag = ATAG_NONE */ ++ataglist_end: ++ .size ataglist, . - ataglist ++#endif /* ifdef CONFIG_OF / else */ diff --git a/patches/linux-3.9-rc1/0014-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch b/patches/linux-3.9-rc1/0014-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch new file mode 100644 index 0000000..5a288c2 --- /dev/null +++ b/patches/linux-3.9-rc1/0014-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch @@ -0,0 +1,32 @@ +From 30050d485eb2248decba2ccb01d65dfc42685442 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Tue, 13 Dec 2011 21:37:46 +0100 +Subject: [PATCH 14/18] HACK! don't reserve memory for device tree if it's + below PHYS_OFFSET +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows to keep the device tree blob in the unregistered 128k SRAM +on efm32. + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/kernel/devtree.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c +index 70f1bde..808801d 100644 +--- a/arch/arm/kernel/devtree.c ++++ b/arch/arm/kernel/devtree.c +@@ -43,6 +43,10 @@ void __init arm_dt_memblock_reserve(void) + if (!initial_boot_params) + return; + ++ if ((unsigned long)initial_boot_params < PHYS_OFFSET) ++ /* assume the dtb is located in ro memory */ ++ return; ++ + /* Reserve the dtb region */ + memblock_reserve(virt_to_phys(initial_boot_params), + be32_to_cpu(initial_boot_params->totalsize)); diff --git a/patches/linux-3.9-rc1/0015-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch b/patches/linux-3.9-rc1/0015-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch new file mode 100644 index 0000000..236638a --- /dev/null +++ b/patches/linux-3.9-rc1/0015-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch @@ -0,0 +1,37 @@ +From f6063df9bf1dd6fecc86c4a53c2a19fb0e688b0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Wed, 14 Dec 2011 11:03:48 +0100 +Subject: [PATCH 15/18] HACK! make stack dumps provoked by BUG a bit more + helpful +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +the right fix would be to continue unwinding at the end when process is +in handler mode + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/kernel/process.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 047d3e4..ac28d5e 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -329,12 +329,14 @@ void __show_regs(struct pt_regs *regs) + #endif + } + ++#include ++ + void show_regs(struct pt_regs * regs) + { + printk("\n"); + printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); + __show_regs(regs); +- dump_stack(); ++ unwind_backtrace(regs, current); + } + + ATOMIC_NOTIFIER_HEAD(thread_notify_head); diff --git a/patches/linux-3.9-rc1/0016-HACK-ARM-increase-TASK_SIZE-for-MMU.patch b/patches/linux-3.9-rc1/0016-HACK-ARM-increase-TASK_SIZE-for-MMU.patch new file mode 100644 index 0000000..4e3033c --- /dev/null +++ b/patches/linux-3.9-rc1/0016-HACK-ARM-increase-TASK_SIZE-for-MMU.patch @@ -0,0 +1,35 @@ +From 04ab986c338e0ad00c3cf1cd47c7b6a0d8774d0e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 4 Oct 2012 13:32:51 +0200 +Subject: [PATCH 16/18] HACK: ARM: increase TASK_SIZE for !MMU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is needed for strncpy_from_user and friends since + + 8c56cc8 (ARM: 7449/1: use generic strnlen_user and strncpy_from_user functions) + +Signed-off-by: Uwe Kleine-König +--- + arch/arm/include/asm/memory.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h +index 57870ab..9604628 100644 +--- a/arch/arm/include/asm/memory.h ++++ b/arch/arm/include/asm/memory.h +@@ -89,9 +89,12 @@ + * It is difficult to define and perhaps will never meet the original meaning + * of this define that was meant to. + * Fortunately, there is no reference for this in noMMU mode, for now. ++ * ++ * HACK: copy_from_user must even handle copying from flash. So don't impose a ++ * limit at all. Not sure this is correct ... + */ + #ifndef TASK_SIZE +-#define TASK_SIZE (CONFIG_DRAM_SIZE) ++#define TASK_SIZE (~0UL) + #endif + + #ifndef TASK_UNMAPPED_BASE diff --git a/patches/linux-3.9-rc1/0017-HACK-work-around-for-big-images.patch b/patches/linux-3.9-rc1/0017-HACK-work-around-for-big-images.patch new file mode 100644 index 0000000..0105b11 --- /dev/null +++ b/patches/linux-3.9-rc1/0017-HACK-work-around-for-big-images.patch @@ -0,0 +1,21 @@ +From 6e2623a0d8baeebc26d63e45ea6ff74ebcaac0cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Thu, 7 Feb 2013 09:43:24 +0100 +Subject: [PATCH 17/18] HACK! work around for big images + +--- + arch/arm/kernel/head-nommu.S | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S +index e2988bb..a6f510f 100644 +--- a/arch/arm/kernel/head-nommu.S ++++ b/arch/arm/kernel/head-nommu.S +@@ -61,6 +61,7 @@ ENTRY(stext) + #endif + bl __lookup_processor_type @ r5=procinfo r9=cpuid + movs r10, r5 @ invalid processor (r5=0)? ++ it eq + beq __error_p @ yes, error 'p' + + adr lr, BSYM(__after_proc_init) @ return (PIC) address diff --git a/patches/linux-3.9-rc1/0018-wip.patch b/patches/linux-3.9-rc1/0018-wip.patch new file mode 100644 index 0000000..a171067 --- /dev/null +++ b/patches/linux-3.9-rc1/0018-wip.patch @@ -0,0 +1,22 @@ +From e87f15ed635f4a7ac0ec775b63e66bb0622a9dbb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Mon, 11 Mar 2013 16:10:49 +0100 +Subject: [PATCH 18/18] wip + +--- + drivers/mfd/efm32board.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/mfd/efm32board.c b/drivers/mfd/efm32board.c +index 5c74a16..d993111 100644 +--- a/drivers/mfd/efm32board.c ++++ b/drivers/mfd/efm32board.c +@@ -64,6 +64,8 @@ static irqreturn_t efm32board_handler(int irq, void *data) + /* ack BC irq */ + writew(0, ddata->base + INTFLAG); + ++ pr_info("%s: INTFLAG=%hx\n", __func__, val); ++ + while (val) { + int line = __fls(val); + diff --git a/patches/linux-3.9-rc1/rmk-devel-stable-20130309.patch b/patches/linux-3.9-rc1/rmk-devel-stable-20130309.patch new file mode 100644 index 0000000..ecba6ed --- /dev/null +++ b/patches/linux-3.9-rc1/rmk-devel-stable-20130309.patch @@ -0,0 +1,412 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 5b71469..dedf02b 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1684,8 +1684,9 @@ config SCHED_HRTICK + def_bool HIGH_RES_TIMERS + + config THUMB2_KERNEL +- bool "Compile the kernel in Thumb-2 mode" ++ bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY + depends on CPU_V7 && !CPU_V6 && !CPU_V6K ++ default y if CPU_THUMBONLY + select AEABI + select ARM_ASM_UNIFIED + select ARM_UNWIND +diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h +index 5ef4d80..1f3262e 100644 +--- a/arch/arm/include/asm/cp15.h ++++ b/arch/arm/include/asm/cp15.h +@@ -42,6 +42,8 @@ + #define vectors_high() (0) + #endif + ++#ifdef CONFIG_CPU_CP15 ++ + extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ + extern unsigned long cr_alignment; /* defined in entry-armv.S */ + +@@ -82,6 +84,18 @@ static inline void set_copro_access(unsigned int val) + isb(); + } + +-#endif ++#else /* ifdef CONFIG_CPU_CP15 */ ++ ++/* ++ * cr_alignment and cr_no_alignment are tightly coupled to cp15 (at least in the ++ * minds of the developers). Yielding 0 for machines without a cp15 (and making ++ * it read-only) is fine for most cases and saves quite some #ifdeffery. ++ */ ++#define cr_no_alignment UL(0) ++#define cr_alignment UL(0) ++ ++#endif /* ifdef CONFIG_CPU_CP15 / else */ ++ ++#endif /* ifndef __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h +index ad41ec2..7652712 100644 +--- a/arch/arm/include/asm/cputype.h ++++ b/arch/arm/include/asm/cputype.h +@@ -38,6 +38,24 @@ + #define MPIDR_AFFINITY_LEVEL(mpidr, level) \ + ((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK) + ++#define ARM_CPU_IMP_ARM 0x41 ++#define ARM_CPU_IMP_INTEL 0x69 ++ ++#define ARM_CPU_PART_ARM1136 0xB360 ++#define ARM_CPU_PART_ARM1156 0xB560 ++#define ARM_CPU_PART_ARM1176 0xB760 ++#define ARM_CPU_PART_ARM11MPCORE 0xB020 ++#define ARM_CPU_PART_CORTEX_A8 0xC080 ++#define ARM_CPU_PART_CORTEX_A9 0xC090 ++#define ARM_CPU_PART_CORTEX_A5 0xC050 ++#define ARM_CPU_PART_CORTEX_A15 0xC0F0 ++#define ARM_CPU_PART_CORTEX_A7 0xC070 ++ ++#define ARM_CPU_XSCALE_ARCH_MASK 0xe000 ++#define ARM_CPU_XSCALE_ARCH_V1 0x2000 ++#define ARM_CPU_XSCALE_ARCH_V2 0x4000 ++#define ARM_CPU_XSCALE_ARCH_V3 0x6000 ++ + extern unsigned int processor_id; + + #ifdef CONFIG_CPU_CP15 +@@ -50,6 +68,7 @@ extern unsigned int processor_id; + : "cc"); \ + __val; \ + }) ++ + #define read_cpuid_ext(ext_reg) \ + ({ \ + unsigned int __val; \ +@@ -59,29 +78,24 @@ extern unsigned int processor_id; + : "cc"); \ + __val; \ + }) +-#else +-#define read_cpuid(reg) (processor_id) +-#define read_cpuid_ext(reg) 0 +-#endif + +-#define ARM_CPU_IMP_ARM 0x41 +-#define ARM_CPU_IMP_INTEL 0x69 ++#else /* ifdef CONFIG_CPU_CP15 */ + +-#define ARM_CPU_PART_ARM1136 0xB360 +-#define ARM_CPU_PART_ARM1156 0xB560 +-#define ARM_CPU_PART_ARM1176 0xB760 +-#define ARM_CPU_PART_ARM11MPCORE 0xB020 +-#define ARM_CPU_PART_CORTEX_A8 0xC080 +-#define ARM_CPU_PART_CORTEX_A9 0xC090 +-#define ARM_CPU_PART_CORTEX_A5 0xC050 +-#define ARM_CPU_PART_CORTEX_A15 0xC0F0 +-#define ARM_CPU_PART_CORTEX_A7 0xC070 ++/* ++ * read_cpuid and read_cpuid_ext should only ever be called on machines that ++ * have cp15 so warn on other usages. ++ */ ++#define read_cpuid(reg) \ ++ ({ \ ++ WARN_ON_ONCE(1); \ ++ 0; \ ++ }) + +-#define ARM_CPU_XSCALE_ARCH_MASK 0xe000 +-#define ARM_CPU_XSCALE_ARCH_V1 0x2000 +-#define ARM_CPU_XSCALE_ARCH_V2 0x4000 +-#define ARM_CPU_XSCALE_ARCH_V3 0x6000 ++#define read_cpuid_ext(reg) read_cpuid(reg) ++ ++#endif /* ifdef CONFIG_CPU_CP15 / else */ + ++#ifdef CONFIG_CPU_CP15 + /* + * The CPU ID never changes at run time, so we might as well tell the + * compiler that it's constant. Use this function to read the CPU ID +@@ -92,6 +106,15 @@ static inline unsigned int __attribute_const__ read_cpuid_id(void) + return read_cpuid(CPUID_ID); + } + ++#else /* ifdef CONFIG_CPU_CP15 */ ++ ++static inline unsigned int __attribute_const__ read_cpuid_id(void) ++{ ++ return processor_id; ++} ++ ++#endif /* ifdef CONFIG_CPU_CP15 / else */ ++ + static inline unsigned int __attribute_const__ read_cpuid_implementor(void) + { + return (read_cpuid_id() & 0xFF000000) >> 24; +diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h +index 8cacbcd..b6e9f2c 100644 +--- a/arch/arm/include/asm/glue-df.h ++++ b/arch/arm/include/asm/glue-df.h +@@ -18,12 +18,12 @@ + * ================ + * + * We have the following to choose from: +- * arm6 - ARM6 style + * arm7 - ARM7 style + * v4_early - ARMv4 without Thumb early abort handler + * v4t_late - ARMv4 with Thumb late abort handler + * v4t_early - ARMv4 with Thumb early abort handler +- * v5tej_early - ARMv5 with Thumb and Java early abort handler ++ * v5t_early - ARMv5 with Thumb early abort handler ++ * v5tj_early - ARMv5 with Thumb and Java early abort handler + * xscale - ARMv5 with Thumb with Xscale extensions + * v6_early - ARMv6 generic early abort handler + * v7_early - ARMv7 generic early abort handler +@@ -39,19 +39,19 @@ + # endif + #endif + +-#ifdef CONFIG_CPU_ABRT_LV4T ++#ifdef CONFIG_CPU_ABRT_EV4 + # ifdef CPU_DABORT_HANDLER + # define MULTI_DABORT 1 + # else +-# define CPU_DABORT_HANDLER v4t_late_abort ++# define CPU_DABORT_HANDLER v4_early_abort + # endif + #endif + +-#ifdef CONFIG_CPU_ABRT_EV4 ++#ifdef CONFIG_CPU_ABRT_LV4T + # ifdef CPU_DABORT_HANDLER + # define MULTI_DABORT 1 + # else +-# define CPU_DABORT_HANDLER v4_early_abort ++# define CPU_DABORT_HANDLER v4t_late_abort + # endif + #endif + +@@ -63,19 +63,19 @@ + # endif + #endif + +-#ifdef CONFIG_CPU_ABRT_EV5TJ ++#ifdef CONFIG_CPU_ABRT_EV5T + # ifdef CPU_DABORT_HANDLER + # define MULTI_DABORT 1 + # else +-# define CPU_DABORT_HANDLER v5tj_early_abort ++# define CPU_DABORT_HANDLER v5t_early_abort + # endif + #endif + +-#ifdef CONFIG_CPU_ABRT_EV5T ++#ifdef CONFIG_CPU_ABRT_EV5TJ + # ifdef CPU_DABORT_HANDLER + # define MULTI_DABORT 1 + # else +-# define CPU_DABORT_HANDLER v5t_early_abort ++# define CPU_DABORT_HANDLER v5tj_early_abort + # endif + #endif + +diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S +index 854bd22..5b391a6 100644 +--- a/arch/arm/kernel/head-common.S ++++ b/arch/arm/kernel/head-common.S +@@ -98,8 +98,9 @@ __mmap_switched: + str r9, [r4] @ Save processor ID + str r1, [r5] @ Save machine type + str r2, [r6] @ Save atags pointer +- bic r4, r0, #CR_A @ Clear 'A' bit +- stmia r7, {r0, r4} @ Save control register values ++ cmp r7, #0 ++ bicne r4, r0, #CR_A @ Clear 'A' bit ++ stmneia r7, {r0, r4} @ Save control register values + b start_kernel + ENDPROC(__mmap_switched) + +@@ -113,7 +114,11 @@ __mmap_switched_data: + .long processor_id @ r4 + .long __machine_arch_type @ r5 + .long __atags_pointer @ r6 ++#ifdef CONFIG_CPU_CP15 + .long cr_alignment @ r7 ++#else ++ .long 0 @ r7 ++#endif + .long init_thread_union + THREAD_START_SP @ sp + .size __mmap_switched_data, . - __mmap_switched_data + +diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S +index 2c228a0..6a2e09c 100644 +--- a/arch/arm/kernel/head-nommu.S ++++ b/arch/arm/kernel/head-nommu.S +@@ -32,15 +32,21 @@ + * numbers for r1. + * + */ +- .arm + + __HEAD ++ ++#ifdef CONFIG_CPU_THUMBONLY ++ .thumb ++ENTRY(stext) ++#else ++ .arm + ENTRY(stext) + + THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. + THUMB( bx r9 ) @ If this is a Thumb-2 kernel, + THUMB( .thumb ) @ switch to Thumb now. + THUMB(1: ) ++#endif + + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode + @ and irqs disabled +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index 3f6cbb2..1cc9e17 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -291,10 +291,10 @@ static int cpu_has_aliasing_icache(unsigned int arch) + + static void __init cacheid_init(void) + { +- unsigned int cachetype = read_cpuid_cachetype(); + unsigned int arch = cpu_architecture(); + + if (arch >= CPU_ARCH_ARMv6) { ++ unsigned int cachetype = read_cpuid_cachetype(); + if ((cachetype & (7 << 29)) == 4 << 29) { + /* ARMv7 register format */ + arch = CPU_ARCH_ARMv7; +diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c +index 45eac87..5bc1a63 100644 +--- a/arch/arm/kernel/smp_scu.c ++++ b/arch/arm/kernel/smp_scu.c +@@ -41,7 +41,7 @@ void scu_enable(void __iomem *scu_base) + + #ifdef CONFIG_ARM_ERRATA_764369 + /* Cortex-A9 only */ +- if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) { ++ if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090) { + scu_ctrl = __raw_readl(scu_base + 0x30); + if (!(scu_ctrl & 1)) + __raw_writel(scu_ctrl | 0x1, scu_base + 0x30); +diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c +index 8a68f1e..577298e 100644 +--- a/arch/arm/mach-omap2/id.c ++++ b/arch/arm/mach-omap2/id.c +@@ -300,7 +300,7 @@ void __init omap3xxx_check_revision(void) + * If the processor type is Cortex-A8 and the revision is 0x0 + * it means its Cortex r0p0 which is 3430 ES1.0. + */ +- cpuid = read_cpuid(CPUID_ID); ++ cpuid = read_cpuid_id(); + if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) { + omap_revision = OMAP3430_REV_ES1_0; + cpu_rev = "1.0"; +@@ -460,7 +460,7 @@ void __init omap4xxx_check_revision(void) + * Use ARM register to detect the correct ES version + */ + if (!rev && (hawkeye != 0xb94e) && (hawkeye != 0xb975)) { +- idcode = read_cpuid(CPUID_ID); ++ idcode = read_cpuid_id(); + rev = (idcode & 0xf) - 1; + } + +diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c +index d972721..7f5626d 100644 +--- a/arch/arm/mach-omap2/omap-smp.c ++++ b/arch/arm/mach-omap2/omap-smp.c +@@ -209,7 +209,7 @@ static void __init omap4_smp_init_cpus(void) + unsigned int i = 0, ncores = 1, cpu_id; + + /* Use ARM cpuid check here, as SoC detection will not work so early */ +- cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; ++ cpu_id = read_cpuid_id() & CPU_MASK; + if (cpu_id == CPU_CORTEX_A9) { + /* + * Currently we can't call ioremap here because +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 025d173..cb812a1 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -397,6 +397,13 @@ config CPU_V7 + select CPU_PABRT_V7 + select CPU_TLB_V7 if MMU + ++config CPU_THUMBONLY ++ bool ++ # There are no CPUs available with MMU that don't implement an ARM ISA: ++ depends on !MMU ++ help ++ Select this if your CPU doesn't support the 32 bit ARM instructions. ++ + # Figure out what processor architecture version we should be using. + # This defines the compiler instruction set which depends on the machine type. + config CPU_32v3 +@@ -608,7 +615,7 @@ config ARCH_DMA_ADDR_T_64BIT + bool + + config ARM_THUMB +- bool "Support Thumb user binaries" ++ bool "Support Thumb user binaries" if !CPU_THUMBONLY + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON + default y + help +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index db26e2e..6f4585b 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -961,12 +961,14 @@ static int __init alignment_init(void) + return -ENOMEM; + #endif + ++#ifdef CONFIG_CPU_CP15 + if (cpu_is_v6_unaligned()) { + cr_alignment &= ~CR_A; + cr_no_alignment &= ~CR_A; + set_cr(cr_alignment); + ai_usermode = safe_usermode(ai_usermode, false); + } ++#endif + + hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN, + "alignment exception"); +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index e95a996..c6d45c8 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -112,6 +112,7 @@ static struct cachepolicy cache_policies[] __initdata = { + } + }; + ++#ifdef CONFIG_CPU_CP15 + /* + * These are useful for identifying cache coherency + * problems by allowing the cache or the cache and +@@ -210,6 +211,22 @@ void adjust_cr(unsigned long mask, unsigned long set) + } + #endif + ++#else /* ifdef CONFIG_CPU_CP15 */ ++ ++static int __init early_cachepolicy(char *p) ++{ ++ pr_warning("cachepolicy kernel parameter not supported without cp15\n"); ++} ++early_param("cachepolicy", early_cachepolicy); ++ ++static int __init noalign_setup(char *__unused) ++{ ++ pr_warning("noalign kernel parameter not supported without cp15\n"); ++} ++__setup("noalign", noalign_setup); ++ ++#endif /* ifdef CONFIG_CPU_CP15 / else */ ++ + #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN + #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE + diff --git a/patches/linux-3.9-rc1/series b/patches/linux-3.9-rc1/series new file mode 100644 index 0000000..49ad49c --- /dev/null +++ b/patches/linux-3.9-rc1/series @@ -0,0 +1,19 @@ +rmk-devel-stable-20130309.patch +0001-irqchip-Add-support-for-ARMv7-M-s-NVIC.patch +0002-ARM-Add-base-support-for-ARMv7-M.patch +0003-ARM-ARMv7-M-Add-support-for-exception-handling.patch +0004-ARM-ARMv7-M-Allow-the-building-of-new-kernel-port.patch +0005-hwmon-efm32-adc-new-driver.patch +0006-spi-new-controller-driver-for-efm32-SoCs.patch +0007-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch +0008-ARM-efm32-some-more-stuff.patch +0009-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch +0010-efm-board-controller-driver.patch +0011-ARM-v7m-add-trivial-suspend-support.patch +0012-ARM-efm32-add-trivial-suspend-support.patch +0013-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch +0014-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch +0015-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch +0016-HACK-ARM-increase-TASK_SIZE-for-MMU.patch +0017-HACK-work-around-for-big-images.patch +0018-wip.patch diff --git a/platformconfig b/platformconfig index 5f22a05..36d1718 100644 --- a/platformconfig +++ b/platformconfig @@ -95,8 +95,8 @@ PTXCONF_TARGET_EXTRA_LDFLAGS="-march=armv7-m -mthumb" PTXCONF_KERNEL=y # PTXCONF_KERNEL_INSTALL is not set # PTXCONF_KERNEL_MODULES is not set -PTXCONF_KERNEL_VERSION="3.8-rc5" -PTXCONF_KERNEL_MD5="89f6b41e5a4fbffb9a1004460154ec5a" +PTXCONF_KERNEL_VERSION="3.9-rc1" +PTXCONF_KERNEL_MD5="83a522998c19b8c14793b4815714f959" PTXCONF_KERNEL_ARCH_STRING="arm" # PTXCONF_KERNEL_IMAGE_BZ is not set # PTXCONF_KERNEL_IMAGE_Z is not set -- cgit v1.2.3