diff options
author | Russell King | 2008-01-28 13:21:30 +0000 |
---|---|---|
committer | Russell King | 2008-01-28 13:21:30 +0000 |
commit | c00d4ffdbace1bdc9fdd888e4ba6d207ffa3b679 (patch) | |
tree | 2c9ddd5ae9cd899758b0785d4c7eb4bc200d66df /arch/arm | |
parent | d0d42df2a440003d96c8bf29991c2afb691ef720 (diff) | |
parent | 8f86dda3ed8f05748f2351ae967926227a91ca2a (diff) |
Merge branch 'orion' into devel
* orion: (26 commits)
[ARM] Orion: implement power-off method for QNAP TS-109/209
[ARM] Orion: add support for QNAP TS-109/TS-209
[ARM] Orion: I2C support
[I2C] i2c-mv64xxx: Don't set i2c_adapter.retries
[I2C] Split mv643xx I2C platform support
[ARM] Orion: enable CONFIG_RTC_DRV_M41T80 for D-Link DNS-323
[ARM] Orion defconfig
[ARM] Orion: add support for Orion/MV88F5181 based D-Link DNS-323
[ARM] Orion: MV88F5181 support bits
[ARM] Orion: Buffalo/Revogear Kurobox Pro support
[ARM] OrionNAS RD board support
[ARM] Orion: support for Marvell Orion-2 (88F5281) Development Board
[ARM] Orion: common platform setup for Gigabit Ethernet port
[ARM] Orion: platform device registration for UART, USB and NAND
[ARM] Orion: system timer support
[ARM] Orion edge GPIO IRQ support
[ARM] Orion: IRQ support
[ARM] Orion: provide GPIO method for enabling hardware assisted blinking
[ARM] Orion: GPIO support
[ARM] Orion: programable address map support
...
Conflicts:
arch/arm/Kconfig
arch/arm/Makefile
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 16 | ||||
-rw-r--r-- | arch/arm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 15 | ||||
-rw-r--r-- | arch/arm/configs/orion_defconfig | 1384 | ||||
-rw-r--r-- | arch/arm/mach-orion/Kconfig | 41 | ||||
-rw-r--r-- | arch/arm/mach-orion/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/mach-orion/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-orion/addr-map.c | 484 | ||||
-rw-r--r-- | arch/arm/mach-orion/common.c | 315 | ||||
-rw-r--r-- | arch/arm/mach-orion/common.h | 78 | ||||
-rw-r--r-- | arch/arm/mach-orion/db88f5281-setup.c | 364 | ||||
-rw-r--r-- | arch/arm/mach-orion/dns323-setup.c | 322 | ||||
-rw-r--r-- | arch/arm/mach-orion/gpio.c | 225 | ||||
-rw-r--r-- | arch/arm/mach-orion/irq.c | 241 | ||||
-rw-r--r-- | arch/arm/mach-orion/kurobox_pro-setup.c | 234 | ||||
-rw-r--r-- | arch/arm/mach-orion/pci.c | 557 | ||||
-rw-r--r-- | arch/arm/mach-orion/rd88f5182-setup.c | 306 | ||||
-rw-r--r-- | arch/arm/mach-orion/time.c | 181 | ||||
-rw-r--r-- | arch/arm/mach-orion/ts209-setup.c | 335 | ||||
-rw-r--r-- | arch/arm/mm/Kconfig | 25 | ||||
-rw-r--r-- | arch/arm/mm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mm/proc-feroceon.S | 506 |
22 files changed, 5635 insertions, 5 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e53b0ed9d00a..6835a4c8affa 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -334,6 +334,16 @@ config ARCH_MXC help Support for Freescale MXC/iMX-based family of processors +config ARCH_ORION + bool "Marvell Orion" + depends on MMU + select PCI + select GENERIC_GPIO + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + help + Support for Marvell Orion System on Chip family. + config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" help @@ -454,6 +464,8 @@ source "arch/arm/mach-omap1/Kconfig" source "arch/arm/mach-omap2/Kconfig" +source "arch/arm/mach-orion/Kconfig" + source "arch/arm/plat-s3c24xx/Kconfig" source "arch/arm/plat-s3c/Kconfig" @@ -732,7 +744,7 @@ config LEDS ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ ARCH_AT91 || MACH_TRIZEPS4 || ARCH_DAVINCI || \ - ARCH_KS8695 + ARCH_KS8695 || MACH_RD88F5182 help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. @@ -967,7 +979,7 @@ config FPE_FASTFPE config VFP bool "VFP-format floating point maths" - depends on CPU_V6 || CPU_ARM926T || CPU_V7 + depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON help Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index dd220d189843..7b8ff66febe1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -139,6 +139,7 @@ endif machine-$(CONFIG_ARCH_KS8695) := ks8695 incdir-$(CONFIG_ARCH_MXC) := mxc machine-$(CONFIG_ARCH_MX3) := mx3 + machine-$(CONFIG_ARCH_ORION) := orion machine-$(CONFIG_ARCH_MSM7X00A) := msm ifeq ($(CONFIG_ARCH_EBSA110),y) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 5cac46a19bb7..3c2c8f2a1dc4 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -623,6 +623,12 @@ proc_types: b __armv4_mmu_cache_off b __armv4_mmu_cache_flush + .word 0x56055310 @ Feroceon + .word 0xfffffff0 + b __armv4_mmu_cache_on + b __armv4_mmu_cache_off + b __armv5tej_mmu_cache_flush + @ These match on the architecture ID .word 0x00020000 @ ARMv4T @@ -641,7 +647,7 @@ proc_types: .word 0x000f0000 b __armv4_mmu_cache_on b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + b __armv5tej_mmu_cache_flush .word 0x0007b000 @ ARMv6 .word 0x000ff000 @@ -821,6 +827,13 @@ iflush: mcr p15, 0, r10, c7, c10, 4 @ drain WB mov pc, lr +__armv5tej_mmu_cache_flush: +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache + bne 1b + mcr p15, 0, r0, c7, c5, 0 @ flush I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + __armv4_mmu_cache_flush: mov r2, #64*1024 @ default: 32K dcache size (*2) mov r11, #32 @ default: 32 byte line size diff --git a/arch/arm/configs/orion_defconfig b/arch/arm/configs/orion_defconfig new file mode 100644 index 000000000000..17a55def1103 --- /dev/null +++ b/arch/arm/configs/orion_defconfig @@ -0,0 +1,1384 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.24-rc3 +# Wed Nov 28 15:13:57 2007 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 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_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_MXC is not set +CONFIG_ARCH_ORION=y +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set + +# +# Orion Implementations +# +CONFIG_MACH_DB88F5281=y +CONFIG_MACH_RD88F5182=y +CONFIG_MACH_KUROBOX_PRO=y +CONFIG_MACH_DNS323=y +CONFIG_MACH_TS209=y + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_FEROCEON=y +CONFIG_CPU_FEROCEON_OLD_ID=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_LEDS=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_SUSPEND_UP_POSSIBLE=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE 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=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# 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_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# 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_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_EXT=y +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_FTL=y +CONFIG_NFTL=y +# CONFIG_NFTL_RW is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +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=y +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 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_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_ORION=y +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +CONFIG_SCSI_MVSATA=y + +# +# Sata options +# +# CONFIG_MV_SATA_SUPPORT_ATAPI is not set +# CONFIG_MV_SATA_ENABLE_1MB_IOS is not set +CONFIG_SATA_NO_DEBUG=y +# CONFIG_SATA_DEBUG_ON_ERROR is not set +# CONFIG_SATA_FULL_DEBUG is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_SRP is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set +# CONFIG_ARCNET is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000E is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +CONFIG_SKGE=y +CONFIG_SKY2=y +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_TIGON3=y +# CONFIG_BNX2 is not set +CONFIG_MV643XX_ETH=y +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +CONFIG_NETDEV_10000=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +CONFIG_I2C_MV64XXX=y + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_SL811_HCD=y +# CONFIG_USB_R8A66597_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +CONFIG_USB_PRINTER=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +# CONFIG_USB_STORAGE_ISD200 is not set +CONFIG_USB_STORAGE_DPCM=y +# CONFIG_USB_STORAGE_USBAT is not set +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_GPIO is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_RS5C372=y +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +CONFIG_RTC_DRV_M41T80=y +# CONFIG_RTC_DRV_M41T80_WDT is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# 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=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +CONFIG_LDM_DEBUG=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set +CONFIG_INSTRUMENTATION=y +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_FRAME_POINTER=y +# CONFIG_SAMPLES is not set +CONFIG_DEBUG_USER=y + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_MANAGER=m +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-orion/Kconfig b/arch/arm/mach-orion/Kconfig new file mode 100644 index 000000000000..1dcbb6ac5a30 --- /dev/null +++ b/arch/arm/mach-orion/Kconfig @@ -0,0 +1,41 @@ +if ARCH_ORION + +menu "Orion Implementations" + +config MACH_DB88F5281 + bool "Marvell Orion-2 Development Board" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-2 (88F5281) Development Board + +config MACH_RD88F5182 + bool "Marvell Orion-NAS Reference Design" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-NAS (88F5182) RD2 + +config MACH_KUROBOX_PRO + bool "KuroBox Pro" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + KuroBox Pro platform. + +config MACH_DNS323 + bool "D-Link DNS-323" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + D-Link DNS-323 platform. + +config MACH_TS209 + bool "QNAP TS-109/TS-209" + help + Say 'Y' here if you want your kernel to support the + QNAP TS-109/TS-209 platform. + +endmenu + +endif diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile new file mode 100644 index 000000000000..f91d937a73e8 --- /dev/null +++ b/arch/arm/mach-orion/Makefile @@ -0,0 +1,6 @@ +obj-y += common.o addr-map.o pci.o gpio.o irq.o time.o +obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o +obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o +obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o +obj-$(CONFIG_MACH_DNS323) += dns323-setup.o +obj-$(CONFIG_MACH_TS209) += ts209-setup.o diff --git a/arch/arm/mach-orion/Makefile.boot b/arch/arm/mach-orion/Makefile.boot new file mode 100644 index 000000000000..67039c3e0c48 --- /dev/null +++ b/arch/arm/mach-orion/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-orion/addr-map.c b/arch/arm/mach-orion/addr-map.c new file mode 100644 index 000000000000..488da3811a68 --- /dev/null +++ b/arch/arm/mach-orion/addr-map.c @@ -0,0 +1,484 @@ +/* + * arch/arm/mach-orion/addr-map.c + * + * Address map functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <asm/hardware.h> +#include "common.h" + +/* + * The Orion has fully programable address map. There's a separate address + * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB, + * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own + * address decode windows that allow it to access any of the Orion resources. + * + * CPU address decoding -- + * Linux assumes that it is the boot loader that already setup the access to + * DDR and internal registers. + * Setup access to PCI and PCI-E IO/MEM space is issued by core.c. + * Setup access to various devices located on the device bus interface (e.g. + * flashes, RTC, etc) should be issued by machine-setup.c according to + * specific board population (by using orion_setup_cpu_win()). + * + * Non-CPU Masters address decoding -- + * Unlike the CPU, we setup the access from Orion's master interfaces to DDR + * banks only (the typical use case). + * Setup access for each master to DDR is issued by common.c. + * + * Note: although orion_setbits() and orion_clrbits() are not atomic + * no locking is necessary here since code in this file is only called + * at boot time when there is no concurrency issues. + */ + +/* + * Generic Address Decode Windows bit settings + */ +#define TARGET_DDR 0 +#define TARGET_PCI 3 +#define TARGET_PCIE 4 +#define TARGET_DEV_BUS 1 +#define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \ + ((n) == 1) ? 0xd : \ + ((n) == 2) ? 0xb : \ + ((n) == 3) ? 0x7 : 0xf) +#define ATTR_PCIE_MEM 0x59 +#define ATTR_PCIE_IO 0x51 +#define ATTR_PCI_MEM 0x59 +#define ATTR_PCI_IO 0x51 +#define ATTR_DEV_CS0 0x1e +#define ATTR_DEV_CS1 0x1d +#define ATTR_DEV_CS2 0x1b +#define ATTR_DEV_BOOT 0xf +#define WIN_EN 1 + +/* + * Helpers to get DDR banks info + */ +#define DDR_BASE_CS(n) ORION_DDR_REG(0x1500 + ((n) * 8)) +#define DDR_SIZE_CS(n) ORION_DDR_REG(0x1504 + ((n) * 8)) +#define DDR_MAX_CS 4 +#define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1) +#define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000) +#define DDR_BANK_EN 1 + +/* + * CPU Address Decode Windows registers + */ +#define CPU_WIN_CTRL(n) ORION_BRIDGE_REG(0x000 | ((n) << 4)) +#define CPU_WIN_BASE(n) ORION_BRIDGE_REG(0x004 | ((n) << 4)) +#define CPU_WIN_REMAP_LO(n) ORION_BRIDGE_REG(0x008 | ((n) << 4)) +#define CPU_WIN_REMAP_HI(n) ORION_BRIDGE_REG(0x00c | ((n) << 4)) +#define CPU_MAX_WIN 8 + +/* + * Use this CPU address decode windows allocation + */ +#define CPU_WIN_PCIE_IO 0 +#define CPU_WIN_PCI_IO 1 +#define CPU_WIN_PCIE_MEM 2 +#define CPU_WIN_PCI_MEM 3 +#define CPU_WIN_DEV_BOOT 4 +#define CPU_WIN_DEV_CS0 5 +#define CPU_WIN_DEV_CS1 6 +#define CPU_WIN_DEV_CS2 7 + +/* + * PCIE Address Decode Windows registers + */ +#define PCIE_BAR_CTRL(n) ORION_PCIE_REG(0x1804 + ((n - 1) * 4)) +#define PCIE_BAR_LO(n) ORION_PCIE_REG(0x0010 + ((n) * 8)) +#define PCIE_BAR_HI(n) ORION_PCIE_REG(0x0014 + ((n) * 8)) +#define PCIE_WIN_CTRL(n) ORION_PCIE_REG(0x1820 + ((n) << 4)) +#define PCIE_WIN_BASE(n) ORION_PCIE_REG(0x1824 + ((n) << 4)) +#define PCIE_WIN_REMAP(n) ORION_PCIE_REG(0x182c + ((n) << 4)) +#define PCIE_DEFWIN_CTRL ORION_PCIE_REG(0x18b0) +#define PCIE_EXPROM_WIN_CTRL ORION_PCIE_REG(0x18c0) +#define PCIE_EXPROM_WIN_REMP ORION_PCIE_REG(0x18c4) +#define PCIE_MAX_BARS 3 +#define PCIE_MAX_WINS 5 + +/* + * Use PCIE BAR '1' for all DDR banks + */ +#define PCIE_DRAM_BAR 1 + +/* + * PCI Address Decode Windows registers + */ +#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION_PCI_REG(0xc08) : \ + ((n) == 1) ? ORION_PCI_REG(0xd08) : \ + ((n) == 2) ? ORION_PCI_REG(0xc0c) : \ + ((n) == 3) ? ORION_PCI_REG(0xd0c) : 0) +#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION_PCI_REG(0xc48) : \ + ((n) == 1) ? ORION_PCI_REG(0xd48) : \ + ((n) == 2) ? ORION_PCI_REG(0xc4c) : \ + ((n) == 3) ? ORION_PCI_REG(0xd4c) : 0) +#define PCI_BAR_ENABLE ORION_PCI_REG(0xc3c) +#define PCI_CTRL_BASE_LO(n) ORION_PCI_REG(0x1e00 | ((n) << 4)) +#define PCI_CTRL_BASE_HI(n) ORION_PCI_REG(0x1e04 | ((n) << 4)) +#define PCI_CTRL_SIZE(n) ORION_PCI_REG(0x1e08 | ((n) << 4)) +#define PCI_ADDR_DECODE_CTRL ORION_PCI_REG(0xd3c) + +/* + * PCI configuration heleprs for BAR settings + */ +#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1) +#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10) +#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14) + +/* + * Gigabit Ethernet Address Decode Windows registers + */ +#define ETH_WIN_BASE(win) ORION_ETH_REG(0x200 + ((win) * 8)) +#define ETH_WIN_SIZE(win) ORION_ETH_REG(0x204 + ((win) * 8)) +#define ETH_WIN_REMAP(win) ORION_ETH_REG(0x280 + ((win) * 4)) +#define ETH_WIN_EN ORION_ETH_REG(0x290) +#define ETH_WIN_PROT ORION_ETH_REG(0x294) +#define ETH_MAX_WIN 6 +#define ETH_MAX_REMAP_WIN 4 + +/* + * USB Address Decode Windows registers + */ +#define USB_WIN_CTRL(i, w) ((i == 0) ? ORION_USB0_REG(0x320 + ((w) << 4)) \ + : ORION_USB1_REG(0x320 + ((w) << 4))) +#define USB_WIN_BASE(i, w) ((i == 0) ? ORION_USB0_REG(0x324 + ((w) << 4)) \ + : ORION_USB1_REG(0x324 + ((w) << 4))) +#define USB_MAX_WIN 4 + +/* + * SATA Address Decode Windows registers + */ +#define SATA_WIN_CTRL(win) ORION_SATA_REG(0x30 + ((win) * 0x10)) +#define SATA_WIN_BASE(win) ORION_SATA_REG(0x34 + ((win) * 0x10)) +#define SATA_MAX_WIN 4 + +static int __init orion_cpu_win_can_remap(u32 win) +{ + u32 dev, rev; + + orion_pcie_id(&dev, &rev); + if ((dev == MV88F5281_DEV_ID && win < 4) + || (dev == MV88F5182_DEV_ID && win < 2) + || (dev == MV88F5181_DEV_ID && win < 2)) + return 1; + + return 0; +} + +void __init orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap) +{ + u32 win, attr, ctrl; + + switch (target) { + case ORION_PCIE_IO: + target = TARGET_PCIE; + attr = ATTR_PCIE_IO; + win = CPU_WIN_PCIE_IO; + break; + case ORION_PCI_IO: + target = TARGET_PCI; + attr = ATTR_PCI_IO; + win = CPU_WIN_PCI_IO; + break; + case ORION_PCIE_MEM: + target = TARGET_PCIE; + attr = ATTR_PCIE_MEM; + win = CPU_WIN_PCIE_MEM; + break; + case ORION_PCI_MEM: + target = TARGET_PCI; + attr = ATTR_PCI_MEM; + win = CPU_WIN_PCI_MEM; + break; + case ORION_DEV_BOOT: + target = TARGET_DEV_BUS; + attr = ATTR_DEV_BOOT; + win = CPU_WIN_DEV_BOOT; + break; + case ORION_DEV0: + target = TARGET_DEV_BUS; + attr = ATTR_DEV_CS0; + win = CPU_WIN_DEV_CS0; + break; + case ORION_DEV1: + target = TARGET_DEV_BUS; + attr = ATTR_DEV_CS1; + win = CPU_WIN_DEV_CS1; + break; + case ORION_DEV2: + target = TARGET_DEV_BUS; + attr = ATTR_DEV_CS2; + win = CPU_WIN_DEV_CS2; + break; + case ORION_DDR: + case ORION_REGS: + /* + * Must be mapped by bootloader. + */ + default: + target = attr = win = -1; + BUG(); + } + + base &= 0xffff0000; + ctrl = (((size - 1) & 0xffff0000) | (attr << 8) | + (target << 4) | WIN_EN); + + orion_write(CPU_WIN_BASE(win), base); + orion_write(CPU_WIN_CTRL(win), ctrl); + + if (orion_cpu_win_can_remap(win)) { + if (remap >= 0) { + orion_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000); + orion_write(CPU_WIN_REMAP_HI(win), 0); + } else { + orion_write(CPU_WIN_REMAP_LO(win), base); + orion_write(CPU_WIN_REMAP_HI(win), 0); + } + } +} + +void __init orion_setup_cpu_wins(void) +{ + int i; + + /* + * First, disable and clear windows + */ + for (i = 0; i < CPU_MAX_WIN; i++) { + orion_write(CPU_WIN_BASE(i), 0); + orion_write(CPU_WIN_CTRL(i), 0); + if (orion_cpu_win_can_remap(i)) { + orion_write(CPU_WIN_REMAP_LO(i), 0); + orion_write(CPU_WIN_REMAP_HI(i), 0); + } + } + + /* + * Setup windows for PCI+PCIE IO+MAM space + */ + orion_setup_cpu_win(ORION_PCIE_IO, ORION_PCIE_IO_BASE, + ORION_PCIE_IO_SIZE, ORION_PCIE_IO_REMAP); + orion_setup_cpu_win(ORION_PCI_IO, ORION_PCI_IO_BASE, + ORION_PCI_IO_SIZE, ORION_PCI_IO_REMAP); + orion_setup_cpu_win(ORION_PCIE_MEM, ORION_PCIE_MEM_BASE, + ORION_PCIE_MEM_SIZE, -1); + orion_setup_cpu_win(ORION_PCI_MEM, ORION_PCI_MEM_BASE, + ORION_PCI_MEM_SIZE, -1); +} + +/* + * Setup PCIE BARs and Address Decode Wins: + * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks + * WIN[0-3] -> DRAM bank[0-3] + */ +void __init orion_setup_pcie_wins(void) +{ + u32 base, size, i; + + /* + * First, disable and clear BARs and windows + */ + for (i = 1; i < PCIE_MAX_BARS; i++) { + orion_write(PCIE_BAR_CTRL(i), 0); + orion_write(PCIE_BAR_LO(i), 0); + orion_write(PCIE_BAR_HI(i), 0); + } + + for (i = 0; i < PCIE_MAX_WINS; i++) { + orion_write(PCIE_WIN_CTRL(i), 0); + orion_write(PCIE_WIN_BASE(i), 0); + orion_write(PCIE_WIN_REMAP(i), 0); + } + + /* + * Setup windows for DDR banks. Count total DDR size on the fly. + */ + base = DDR_REG_TO_BASE(orion_read(DDR_BASE_CS(0))); + size = 0; + for (i = 0; i < DDR_MAX_CS; i++) { + u32 bank_base, bank_size; + bank_size = orion_read(DDR_SIZE_CS(i)); + bank_base = orion_read(DDR_BASE_CS(i)); + if (bank_size & DDR_BANK_EN) { + bank_size = DDR_REG_TO_SIZE(bank_size); + bank_base = DDR_REG_TO_BASE(bank_base); + orion_write(PCIE_WIN_BASE(i), bank_base & 0xffff0000); + orion_write(PCIE_WIN_REMAP(i), 0); + orion_write(PCIE_WIN_CTRL(i), + ((bank_size-1) & 0xffff0000) | + (ATTR_DDR_CS(i) << 8) | + (TARGET_DDR << 4) | + (PCIE_DRAM_BAR << 1) | WIN_EN); + size += bank_size; + } + } + + /* + * Setup BAR[1] to all DRAM banks + */ + orion_write(PCIE_BAR_LO(PCIE_DRAM_BAR), base & 0xffff0000); + orion_write(PCIE_BAR_HI(PCIE_DRAM_BAR), 0); + orion_write(PCIE_BAR_CTRL(PCIE_DRAM_BAR), + ((size - 1) & 0xffff0000) | WIN_EN); +} + +void __init orion_setup_pci_wins(void) +{ + u32 base, size, i; + + /* + * First, disable windows + */ + orion_write(PCI_BAR_ENABLE, 0xffffffff); + + /* + * Setup windows for DDR banks. + */ + for (i = 0; i < DDR_MAX_CS; i++) { + base = orion_read(DDR_BASE_CS(i)); + size = orion_read(DDR_SIZE_CS(i)); + if (size & DDR_BANK_EN) { + u32 bus, dev, func, reg, val; + size = DDR_REG_TO_SIZE(size); + base = DDR_REG_TO_BASE(base); + bus = orion_pci_local_bus_nr(); + dev = orion_pci_local_dev_nr(); + func = PCI_CONF_FUNC_BAR_CS(i); + reg = PCI_CONF_REG_BAR_LO_CS(i); + orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val); + orion_pci_hw_wr_conf(bus, dev, func, reg, 4, + (base & 0xfffff000) | (val & 0xfff)); + reg = PCI_CONF_REG_BAR_HI_CS(i); + orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0); + orion_write(PCI_BAR_SIZE_DDR_CS(i), + (size - 1) & 0xfffff000); + orion_write(PCI_BAR_REMAP_DDR_CS(i), + base & 0xfffff000); + orion_clrbits(PCI_BAR_ENABLE, (1 << i)); + } + } + + /* + * Disable automatic update of address remaping when writing to BARs + */ + orion_setbits(PCI_ADDR_DECODE_CTRL, 1); +} + +void __init orion_setup_usb_wins(void) +{ + int i; + u32 usb_if, dev, rev; + u32 max_usb_if = 1; + + orion_pcie_id(&dev, &rev); + if (dev == MV88F5182_DEV_ID) + max_usb_if = 2; + + for (usb_if = 0; usb_if < max_usb_if; usb_if++) { + /* + * First, disable and clear windows + */ + for (i = 0; i < USB_MAX_WIN; i++) { + orion_write(USB_WIN_BASE(usb_if, i), 0); + orion_write(USB_WIN_CTRL(usb_if, i), 0); + } + + /* + * Setup windows for DDR banks. + */ + for (i = 0; i < DDR_MAX_CS; i++) { + u32 base, size; + size = orion_read(DDR_SIZE_CS(i)); + base = orion_read(DDR_BASE_CS(i)); + if (size & DDR_BANK_EN) { + base = DDR_REG_TO_BASE(base); + size = DDR_REG_TO_SIZE(size); + orion_write(USB_WIN_CTRL(usb_if, i), + ((size-1) & 0xffff0000) | + (ATTR_DDR_CS(i) << 8) | + (TARGET_DDR << 4) | WIN_EN); + orion_write(USB_WIN_BASE(usb_if, i), + base & 0xffff0000); + } + } + } +} + +void __init orion_setup_eth_wins(void) +{ + int i; + + /* + * First, disable and clear windows + */ + for (i = 0; i < ETH_MAX_WIN; i++) { + orion_write(ETH_WIN_BASE(i), 0); + orion_write(ETH_WIN_SIZE(i), 0); + orion_setbits(ETH_WIN_EN, 1 << i); + orion_clrbits(ETH_WIN_PROT, 0x3 << (i * 2)); + if (i < ETH_MAX_REMAP_WIN) + orion_write(ETH_WIN_REMAP(i), 0); + } + + /* + * Setup windows for DDR banks. + */ + for (i = 0; i < DDR_MAX_CS; i++) { + u32 base, size; + size = orion_read(DDR_SIZE_CS(i)); + base = orion_read(DDR_BASE_CS(i)); + if (size & DDR_BANK_EN) { + base = DDR_REG_TO_BASE(base); + size = DDR_REG_TO_SIZE(size); + orion_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000); + orion_write(ETH_WIN_BASE(i), (base & 0xffff0000) | + (ATTR_DDR_CS(i) << 8) | + TARGET_DDR); + orion_clrbits(ETH_WIN_EN, 1 << i); + orion_setbits(ETH_WIN_PROT, 0x3 << (i * 2)); + } + } +} + +void __init orion_setup_sata_wins(void) +{ + int i; + + /* + * First, disable and clear windows + */ + for (i = 0; i < SATA_MAX_WIN; i++) { + orion_write(SATA_WIN_BASE(i), 0); + orion_write(SATA_WIN_CTRL(i), 0); + } + + /* + * Setup windows for DDR banks. + */ + for (i = 0; i < DDR_MAX_CS; i++) { + u32 base, size; + size = orion_read(DDR_SIZE_CS(i)); + base = orion_read(DDR_BASE_CS(i)); + if (size & DDR_BANK_EN) { + base = DDR_REG_TO_BASE(base); + size = DDR_REG_TO_SIZE(size); + orion_write(SATA_WIN_CTRL(i), + ((size-1) & 0xffff0000) | + (ATTR_DDR_CS(i) << 8) | + (TARGET_DDR << 4) | WIN_EN); + orion_write(SATA_WIN_BASE(i), + base & 0xffff0000); + } + } +} diff --git a/arch/arm/mach-orion/common.c b/arch/arm/mach-orion/common.c new file mode 100644 index 000000000000..5e20b6b32508 --- /dev/null +++ b/arch/arm/mach-orion/common.c @@ -0,0 +1,315 @@ +/* + * arch/arm/mach-orion/common.c + * + * Core functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> +#include <linux/mv643xx_eth.h> +#include <linux/mv643xx_i2c.h> +#include <asm/page.h> +#include <asm/timex.h> +#include <asm/mach/map.h> +#include <asm/arch/orion.h> +#include "common.h" + +/***************************************************************************** + * I/O Address Mapping + ****************************************************************************/ +static struct map_desc orion_io_desc[] __initdata = { + { + .virtual = ORION_REGS_BASE, + .pfn = __phys_to_pfn(ORION_REGS_BASE), + .length = ORION_REGS_SIZE, + .type = MT_DEVICE + }, + { + .virtual = ORION_PCIE_IO_BASE, + .pfn = __phys_to_pfn(ORION_PCIE_IO_BASE), + .length = ORION_PCIE_IO_SIZE, + .type = MT_DEVICE + }, + { + .virtual = ORION_PCI_IO_BASE, + .pfn = __phys_to_pfn(ORION_PCI_IO_BASE), + .length = ORION_PCI_IO_SIZE, + .type = MT_DEVICE + }, + { + .virtual = ORION_PCIE_WA_BASE, + .pfn = __phys_to_pfn(ORION_PCIE_WA_BASE), + .length = ORION_PCIE_WA_SIZE, + .type = MT_DEVICE + }, +}; + +void __init orion_map_io(void) +{ + iotable_init(orion_io_desc, ARRAY_SIZE(orion_io_desc)); +} + +/***************************************************************************** + * UART + ****************************************************************************/ + +static struct resource orion_uart_resources[] = { + { + .start = UART0_BASE, + .end = UART0_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_ORION_UART0, + .end = IRQ_ORION_UART0, + .flags = IORESOURCE_IRQ, + }, + { + .start = UART1_BASE, + .end = UART1_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_ORION_UART1, + .end = IRQ_ORION_UART1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct plat_serial8250_port orion_uart_data[] = { + { + .mapbase = UART0_BASE, + .membase = (char *)UART0_BASE, + .irq = IRQ_ORION_UART0, + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = ORION_TCLK, + }, + { + .mapbase = UART1_BASE, + .membase = (char *)UART1_BASE, + .irq = IRQ_ORION_UART1, + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = ORION_TCLK, + }, + { }, +}; + +static struct platform_device orion_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = orion_uart_data, + }, + .resource = orion_uart_resources, + .num_resources = ARRAY_SIZE(orion_uart_resources), +}; + +/******************************************************************************* + * USB Controller - 2 interfaces + ******************************************************************************/ + +static struct resource orion_ehci0_resources[] = { + { + .start = ORION_USB0_REG_BASE, + .end = ORION_USB0_REG_BASE + SZ_4K, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_ORION_USB0_CTRL, + .end = IRQ_ORION_USB0_CTRL, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource orion_ehci1_resources[] = { + { + .start = ORION_USB1_REG_BASE, + .end = ORION_USB1_REG_BASE + SZ_4K, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_ORION_USB1_CTRL, + .end = IRQ_ORION_USB1_CTRL, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ehci_dmamask = 0xffffffffUL; + +static struct platform_device orion_ehci0 = { + .name = "orion-ehci", + .id = 0, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = orion_ehci0_resources, + .num_resources = ARRAY_SIZE(orion_ehci0_resources), +}; + +static struct platform_device orion_ehci1 = { + .name = "orion-ehci", + .id = 1, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = orion_ehci1_resources, + .num_resources = ARRAY_SIZE(orion_ehci1_resources), +}; + +/***************************************************************************** + * Gigabit Ethernet port + * (The Orion and Discovery (MV643xx) families use the same Ethernet driver) + ****************************************************************************/ + +static struct resource orion_eth_shared_resources[] = { + { + .start = ORION_ETH_REG_BASE, + .end = ORION_ETH_REG_BASE + 0xffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device orion_eth_shared = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = 1, + .resource = orion_eth_shared_resources, +}; + +static struct resource orion_eth_resources[] = { + { + .name = "eth irq", + .start = IRQ_ORION_ETH_SUM, + .end = IRQ_ORION_ETH_SUM, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device orion_eth = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = 1, + .resource = orion_eth_resources, +}; + +void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data) +{ + orion_eth.dev.platform_data = eth_data; + platform_device_register(&orion_eth_shared); + platform_device_register(&orion_eth); +} + +/***************************************************************************** + * I2C controller + * (The Orion and Discovery (MV643xx) families share the same I2C controller) + ****************************************************************************/ + +static struct mv64xxx_i2c_pdata orion_i2c_pdata = { + .freq_m = 8, /* assumes 166 MHz TCLK */ + .freq_n = 3, + .timeout = 1000, /* Default timeout of 1 second */ +}; + +static struct resource orion_i2c_resources[] = { + { + .name = "i2c base", + .start = I2C_BASE, + .end = I2C_BASE + 0x20 -1, + .flags = IORESOURCE_MEM, + }, + { + .name = "i2c irq", + .start = IRQ_ORION_I2C, + .end = IRQ_ORION_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device orion_i2c = { + .name = MV64XXX_I2C_CTLR_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(orion_i2c_resources), + .resource = orion_i2c_resources, + .dev = { + .platform_data = &orion_i2c_pdata, + }, +}; + +/***************************************************************************** + * General + ****************************************************************************/ + +/* + * Identify device ID and rev from PCIE configuration header space '0'. + */ +static void orion_id(u32 *dev, u32 *rev, char **dev_name) +{ + orion_pcie_id(dev, rev); + + if (*dev == MV88F5281_DEV_ID) { + if (*rev == MV88F5281_REV_D2) { + *dev_name = "MV88F5281-D2"; + } else if (*rev == MV88F5281_REV_D1) { + *dev_name = "MV88F5281-D1"; + } else { + *dev_name = "MV88F5281-Rev-Unsupported"; + } + } else if (*dev == MV88F5182_DEV_ID) { + if (*rev == MV88F5182_REV_A2) { + *dev_name = "MV88F5182-A2"; + } else { + *dev_name = "MV88F5182-Rev-Unsupported"; + } + } else if (*dev == MV88F5181_DEV_ID) { + if (*rev == MV88F5181_REV_B1) { + *dev_name = "MV88F5181-Rev-B1"; + } else { + *dev_name = "MV88F5181-Rev-Unsupported"; + } + } else { + *dev_name = "Device-Unknown"; + } +} + +void __init orion_init(void) +{ + char *dev_name; + u32 dev, rev; + + orion_id(&dev, &rev, &dev_name); + printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION_TCLK); + + /* + * Setup Orion address map + */ + orion_setup_cpu_wins(); + orion_setup_usb_wins(); + orion_setup_eth_wins(); + orion_setup_pci_wins(); + orion_setup_pcie_wins(); + if (dev == MV88F5182_DEV_ID) + orion_setup_sata_wins(); + + /* + * REgister devices + */ + platform_device_register(&orion_uart); + platform_device_register(&orion_ehci0); + if (dev == MV88F5182_DEV_ID) + platform_device_register(&orion_ehci1); + platform_device_register(&orion_i2c); +} diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h new file mode 100644 index 000000000000..06c10c06f03e --- /dev/null +++ b/arch/arm/mach-orion/common.h @@ -0,0 +1,78 @@ +#ifndef __ARCH_ORION_COMMON_H__ +#define __ARCH_ORION_COMMON_H__ + +/* + * Basic Orion init functions used early by machine-setup. + */ + +void __init orion_map_io(void); +void __init orion_init_irq(void); +void __init orion_init(void); + +/* + * Enumerations and functions for Orion windows mapping. Used by Orion core + * functions to map its interfaces and by the machine-setup to map its on- + * board devices. Details in /mach-orion/addr-map.c + */ + +enum orion_target { + ORION_DEV_BOOT = 0, + ORION_DEV0, + ORION_DEV1, + ORION_DEV2, + ORION_PCIE_MEM, + ORION_PCIE_IO, + ORION_PCI_MEM, + ORION_PCI_IO, + ORION_DDR, + ORION_REGS, + ORION_MAX_TARGETS +}; + +void orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap); +void orion_setup_cpu_wins(void); +void orion_setup_eth_wins(void); +void orion_setup_usb_wins(void); +void orion_setup_pci_wins(void); +void orion_setup_pcie_wins(void); +void orion_setup_sata_wins(void); + +/* + * Shared code used internally by other Orion core functions. + * (/mach-orion/pci.c) + */ + +struct pci_sys_data; +struct pci_bus; + +void orion_pcie_id(u32 *dev, u32 *rev); +u32 orion_pcie_local_bus_nr(void); +u32 orion_pci_local_bus_nr(void); +u32 orion_pci_local_dev_nr(void); +int orion_pci_sys_setup(int nr, struct pci_sys_data *sys); +struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); +int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val); +int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val); + +/* + * Valid GPIO pins according to MPP setup, used by machine-setup. + * (/mach-orion/gpio.c). + */ + +void __init orion_gpio_set_valid_pins(u32 pins); +void gpio_display(void); /* debug */ + +/* + * Orion system timer (clocksource + clockevnt, /mach-orion/time.c) + */ +extern struct sys_timer orion_timer; + +/* + * Pull in Orion Ethernet platform_data, used by machine-setup + */ + +struct mv643xx_eth_platform_data; + +void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data); + +#endif /* __ARCH_ORION_COMMON_H__ */ diff --git a/arch/arm/mach-orion/db88f5281-setup.c b/arch/arm/mach-orion/db88f5281-setup.c new file mode 100644 index 000000000000..cb2a95ce5b57 --- /dev/null +++ b/arch/arm/mach-orion/db88f5281-setup.c @@ -0,0 +1,364 @@ +/* + * arch/arm/mach-orion/db88f5281-setup.c + * + * Marvell Orion-2 Development Board Setup + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/nand.h> +#include <linux/timer.h> +#include <linux/mv643xx_eth.h> +#include <linux/i2c.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <asm/arch/orion.h> +#include <asm/arch/platform.h> +#include "common.h" + +/***************************************************************************** + * DB-88F5281 on board devices + ****************************************************************************/ + +/* + * 512K NOR flash Device bus boot chip select + */ + +#define DB88F5281_NOR_BOOT_BASE 0xf4000000 +#define DB88F5281_NOR_BOOT_SIZE SZ_512K + +/* + * 7-Segment on Device bus chip select 0 + */ + +#define DB88F5281_7SEG_BASE 0xfa000000 +#define DB88F5281_7SEG_SIZE SZ_1K + +/* + * 32M NOR flash on Device bus chip select 1 + */ + +#define DB88F5281_NOR_BASE 0xfc000000 +#define DB88F5281_NOR_SIZE SZ_32M + +/* + * 32M NAND flash on Device bus chip select 2 + */ + +#define DB88F5281_NAND_BASE 0xfa800000 +#define DB88F5281_NAND_SIZE SZ_1K + +/* + * PCI + */ + +#define DB88F5281_PCI_SLOT0_OFFS 7 +#define DB88F5281_PCI_SLOT0_IRQ_PIN 12 +#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN 13 + +/***************************************************************************** + * 512M NOR Flash on Device bus Boot CS + ****************************************************************************/ + +static struct physmap_flash_data db88f5281_boot_flash_data = { + .width = 1, /* 8 bit bus width */ +}; + +static struct resource db88f5281_boot_flash_resource = { + .flags = IORESOURCE_MEM, + .start = DB88F5281_NOR_BOOT_BASE, + .end = DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device db88f5281_boot_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &db88f5281_boot_flash_data, + }, + .num_resources = 1, + .resource = &db88f5281_boot_flash_resource, +}; + +/***************************************************************************** + * 32M NOR Flash on Device bus CS1 + ****************************************************************************/ + +static struct physmap_flash_data db88f5281_nor_flash_data = { + .width = 4, /* 32 bit bus width */ +}; + +static struct resource db88f5281_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = DB88F5281_NOR_BASE, + .end = DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1, +}; + +static struct platform_device db88f5281_nor_flash = { + .name = "physmap-flash", + .id = 1, + .dev = { + .platform_data = &db88f5281_nor_flash_data, + }, + .num_resources = 1, + .resource = &db88f5281_nor_flash_resource, +}; + +/***************************************************************************** + * 32M NAND Flash on Device bus CS2 + ****************************************************************************/ + +static struct mtd_partition db88f5281_nand_parts[] = { + { + .name = "kernel", + .offset = 0, + .size = SZ_2M, + }, + { + .name = "root", + .offset = SZ_2M, + .size = (SZ_16M - SZ_2M), + }, + { + .name = "user", + .offset = SZ_16M, + .size = SZ_8M, + }, + { + .name = "recovery", + .offset = (SZ_16M + SZ_8M), + .size = SZ_8M, + }, +}; + +static struct resource db88f5281_nand_resource = { + .flags = IORESOURCE_MEM, + .start = DB88F5281_NAND_BASE, + .end = DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1, +}; + +static struct orion_nand_data db88f5281_nand_data = { + .parts = db88f5281_nand_parts, + .nr_parts = ARRAY_SIZE(db88f5281_nand_parts), + .cle = 0, + .ale = 1, + .width = 8, +}; + +static struct platform_device db88f5281_nand_flash = { + .name = "orion_nand", + .id = -1, + .dev = { + .platform_data = &db88f5281_nand_data, + }, + .resource = &db88f5281_nand_resource, + .num_resources = 1, +}; + +/***************************************************************************** + * 7-Segment on Device bus CS0 + * Dummy counter every 2 sec + ****************************************************************************/ + +static void __iomem *db88f5281_7seg; +static struct timer_list db88f5281_timer; + +static void db88f5281_7seg_event(unsigned long data) +{ + static int count = 0; + writel(0, db88f5281_7seg + (count << 4)); + count = (count + 1) & 7; + mod_timer(&db88f5281_timer, jiffies + 2 * HZ); +} + +static int __init db88f5281_7seg_init(void) +{ + if (machine_is_db88f5281()) { + db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE, + DB88F5281_7SEG_SIZE); + if (!db88f5281_7seg) { + printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n"); + return -EIO; + } + setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0); + mod_timer(&db88f5281_timer, jiffies + 2 * HZ); + } + + return 0; +} + +__initcall(db88f5281_7seg_init); + +/***************************************************************************** + * PCI + ****************************************************************************/ + +void __init db88f5281_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = DB88F5281_PCI_SLOT0_IRQ_PIN; + if (gpio_request(pin, "PCI Int1") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "db88f5281_pci_preinit faield to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin); + } + + pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN; + if (gpio_request(pin, "PCI Int2") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "db88f5281_pci_preinit faield " + "to set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin); + } +} + +static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* + * PCIE IRQ is connected internally (not GPIO) + */ + if (dev->bus->number == orion_pcie_local_bus_nr()) + return IRQ_ORION_PCIE0_INT; + + /* + * PCI IRQs are connected via GPIOs + */ + switch (slot - DB88F5281_PCI_SLOT0_OFFS) { + case 0: + return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN); + case 1: + case 2: + return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN); + default: + return -1; + } +} + +static struct hw_pci db88f5281_pci __initdata = { + .nr_controllers = 2, + .preinit = db88f5281_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = orion_pci_sys_setup, + .scan = orion_pci_sys_scan_bus, + .map_irq = db88f5281_pci_map_irq, +}; + +static int __init db88f5281_pci_init(void) +{ + if (machine_is_db88f5281()) + pci_common_init(&db88f5281_pci); + + return 0; +} + +subsys_initcall(db88f5281_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ +static struct mv643xx_eth_platform_data db88f5281_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/***************************************************************************** + * RTC DS1339 on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata db88f5281_i2c_rtc = { + .driver_name = "rtc-ds1307", + .type = "ds1339", + .addr = 0x68, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct platform_device *db88f5281_devs[] __initdata = { + &db88f5281_boot_flash, + &db88f5281_nor_flash, + &db88f5281_nand_flash, +}; + +static void __init db88f5281_init(void) +{ + /* + * Basic Orion setup. Need to be called early. + */ + orion_init(); + + /* + * Setup the CPU address decode windows for our on-board devices + */ + orion_setup_cpu_win(ORION_DEV_BOOT, DB88F5281_NOR_BOOT_BASE, + DB88F5281_NOR_BOOT_SIZE, -1); + orion_setup_cpu_win(ORION_DEV0, DB88F5281_7SEG_BASE, + DB88F5281_7SEG_SIZE, -1); + orion_setup_cpu_win(ORION_DEV1, DB88F5281_NOR_BASE, + DB88F5281_NOR_SIZE, -1); + orion_setup_cpu_win(ORION_DEV2, DB88F5281_NAND_BASE, + DB88F5281_NAND_SIZE, -1); + + /* + * Setup Multiplexing Pins: + * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input) + * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2] + * MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3] + * MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1) + * MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3) + * MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator) + * MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2) + * MPP14: NAND_REn[2] MPP15: NAND_WEn[2] + * MPP16: UART1_RX MPP17: UART1_TX + * MPP18: UART1_CTS MPP19: UART1_RTS + * MPP-DEV: DEV_D[16:31] + */ + orion_write(MPP_0_7_CTRL, 0x00222203); + orion_write(MPP_8_15_CTRL, 0x44000000); + orion_write(MPP_16_19_CTRL, 0); + orion_write(MPP_DEV_CTRL, 0); + + orion_gpio_set_valid_pins(0x00003fc3); + + platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs)); + i2c_register_board_info(0, &db88f5281_i2c_rtc, 1); + orion_eth_init(&db88f5281_eth_data); +} + +MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board") + /* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */ + .phys_io = ORION_REGS_BASE, + .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = db88f5281_init, + .map_io = orion_map_io, + .init_irq = orion_init_irq, + .timer = &orion_timer, +MACHINE_END diff --git a/arch/arm/mach-orion/dns323-setup.c b/arch/arm/mach-orion/dns323-setup.c new file mode 100644 index 000000000000..c8a806f249c6 --- /dev/null +++ b/arch/arm/mach-orion/dns323-setup.c @@ -0,0 +1,322 @@ +/* + * arch/arm/mach-orion/dns323-setup.c + * + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <asm/arch/orion.h> +#include <asm/arch/platform.h> +#include "common.h" + +#define DNS323_GPIO_LED_RIGHT_AMBER 1 +#define DNS323_GPIO_LED_LEFT_AMBER 2 +#define DNS323_GPIO_LED_POWER 5 +#define DNS323_GPIO_OVERTEMP 6 +#define DNS323_GPIO_RTC 7 +#define DNS323_GPIO_POWER_OFF 8 +#define DNS323_GPIO_KEY_POWER 9 +#define DNS323_GPIO_KEY_RESET 10 + +/**************************************************************************** + * PCI setup + */ + +static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* PCI-E */ + if (dev->bus->number == orion_pcie_local_bus_nr()) + return IRQ_ORION_PCIE0_INT; + + pr_err("%s: requested mapping for unknown bus\n", __func__); + + return -1; +} + +static struct hw_pci dns323_pci __initdata = { + .nr_controllers = 1, + .swizzle = pci_std_swizzle, + .setup = orion_pci_sys_setup, + .scan = orion_pci_sys_scan_bus, + .map_irq = dns323_pci_map_irq, +}; + +static int __init dns323_pci_init(void) +{ + if (machine_is_dns323()) + pci_common_init(&dns323_pci); + + return 0; +} + +subsys_initcall(dns323_pci_init); + +/**************************************************************************** + * Ethernet + */ + +static struct mv643xx_eth_platform_data dns323_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/**************************************************************************** + * 8MiB NOR flash (Spansion S29GL064M90TFIR4) + * + * Layout as used by D-Link: + * 0x00000000-0x00010000 : "MTD1" + * 0x00010000-0x00020000 : "MTD2" + * 0x00020000-0x001a0000 : "Linux Kernel" + * 0x001a0000-0x007d0000 : "File System" + * 0x007d0000-0x00800000 : "u-boot" + */ + +#define DNS323_NOR_BOOT_BASE 0xf4000000 +#define DNS323_NOR_BOOT_SIZE SZ_8M + +static struct mtd_partition dns323_partitions[] = { + { + .name = "MTD1", + .size = 0x00010000, + .offset = 0, + }, { + .name = "MTD2", + .size = 0x00010000, + .offset = 0x00010000, + }, { + .name = "Linux Kernel", + .size = 0x00180000, + .offset = 0x00020000, + }, { + .name = "File System", + .size = 0x00630000, + .offset = 0x001A0000, + }, { + .name = "u-boot", + .size = 0x00030000, + .offset = 0x007d0000, + } +}; + +static struct physmap_flash_data dns323_nor_flash_data = { + .width = 1, + .parts = dns323_partitions, + .nr_parts = ARRAY_SIZE(dns323_partitions) +}; + +static struct resource dns323_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = DNS323_NOR_BOOT_BASE, + .end = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device dns323_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { .platform_data = &dns323_nor_flash_data, }, + .resource = &dns323_nor_flash_resource, + .num_resources = 1, +}; + +/**************************************************************************** + * GPIO LEDs (simple - doesn't use hardware blinking support) + */ + +static struct gpio_led dns323_leds[] = { + { + .name = "power:blue", + .gpio = DNS323_GPIO_LED_POWER, + .active_low = 1, + }, { + .name = "right:amber", + .gpio = DNS323_GPIO_LED_RIGHT_AMBER, + .active_low = 1, + }, { + .name = "left:amber", + .gpio = DNS323_GPIO_LED_LEFT_AMBER, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data dns323_led_data = { + .num_leds = ARRAY_SIZE(dns323_leds), + .leds = dns323_leds, +}; + +static struct platform_device dns323_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { .platform_data = &dns323_led_data, }, +}; + +/**************************************************************************** + * GPIO Attached Keys + */ + +static struct gpio_keys_button dns323_buttons[] = { + { + .code = KEY_RESTART, + .gpio = DNS323_GPIO_KEY_RESET, + .desc = "Reset Button", + .active_low = 1, + }, + { + .code = KEY_POWER, + .gpio = DNS323_GPIO_KEY_POWER, + .desc = "Power Button", + .active_low = 1, + } +}; + +static struct gpio_keys_platform_data dns323_button_data = { + .buttons = dns323_buttons, + .nbuttons = ARRAY_SIZE(dns323_buttons), +}; + +static struct platform_device dns323_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { .platform_data = &dns323_button_data, }, +}; + +/**************************************************************************** + * General Setup + */ + +static struct platform_device *dns323_plat_devices[] __initdata = { + &dns323_nor_flash, + &dns323_gpio_leds, + &dns323_button_device, +}; + +/* + * On the DNS-323 the following devices are attached via I2C: + * + * i2c addr | chip | description + * 0x3e | GMT G760Af | fan speed PWM controller + * 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible) + * 0x68 | ST M41T80 | RTC w/ alarm + */ +static struct i2c_board_info __initdata dns323_i2c_devices[] = { + { + I2C_BOARD_INFO("g760a", 0x3e), + .type = "g760a", + }, +#if 0 + /* this entry requires the new-style driver model lm75 driver, + * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */ + { + I2C_BOARD_INFO("lm75", 0x48), + .type = "g751", + }, +#endif + { + I2C_BOARD_INFO("rtc-m41t80", 0x68), + .type = "m41t80", + } +}; + +/* DNS-323 specific power off method */ +static void dns323_power_off(void) +{ + pr_info("%s: triggering power-off...\n", __func__); + gpio_set_value(DNS323_GPIO_POWER_OFF, 1); +} + +static void __init dns323_init(void) +{ + /* Setup basic Orion functions. Need to be called early. */ + orion_init(); + + /* setup flash mapping + * CS3 holds a 8 MB Spansion S29GL064M90TFIR4 + */ + orion_setup_cpu_win(ORION_DEV_BOOT, DNS323_NOR_BOOT_BASE, + DNS323_NOR_BOOT_SIZE, -1); + + /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE + * + * Open a special address decode windows for the PCIE WA. + */ + orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE); + orion_write(ORION_REGS_BASE | 0x20070, + (0x7941 | (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16)); + + /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */ + orion_write(MPP_0_7_CTRL, 0); + orion_write(MPP_8_15_CTRL, 0); + orion_write(MPP_16_19_CTRL, 0); + orion_write(MPP_DEV_CTRL, 0); + + /* Define used GPIO pins + + GPIO Map: + + | 0 | | PEX_RST_OUT (not controlled by GPIO) + | 1 | Out | right amber LED (= sata ch0 LED) (low-active) + | 2 | Out | left amber LED (= sata ch1 LED) (low-active) + | 3 | Out | //unknown// + | 4 | Out | power button LED (low-active, together with pin #5) + | 5 | Out | power button LED (low-active, together with pin #4) + | 6 | In | GMT G751-2f overtemp. shutdown signal (low-active) + | 7 | In | M41T80 nIRQ/OUT/SQW signal + | 8 | Out | triggers power off (high-active) + | 9 | In | power button switch (low-active) + | 10 | In | reset button switch (low-active) + | 11 | Out | //unknown// + | 12 | Out | //unknown// + | 13 | Out | //unknown// + | 14 | Out | //unknown// + | 15 | Out | //unknown// + */ + orion_gpio_set_valid_pins(0x07f6); + + /* register dns323 specific power-off method */ + if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0) + || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)) + pr_err("DNS323: failed to setup power-off GPIO\n"); + + pm_power_off = dns323_power_off; + + /* register flash and other platform devices */ + platform_add_devices(dns323_plat_devices, + ARRAY_SIZE(dns323_plat_devices)); + + i2c_register_board_info(0, dns323_i2c_devices, + ARRAY_SIZE(dns323_i2c_devices)); + + orion_eth_init(&dns323_eth_data); +} + +/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */ +MACHINE_START(DNS323, "D-Link DNS-323") + /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */ + .phys_io = ORION_REGS_BASE, + .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = dns323_init, + .map_io = orion_map_io, + .init_irq = orion_init_irq, + .timer = &orion_timer, +MACHINE_END diff --git a/arch/arm/mach-orion/gpio.c b/arch/arm/mach-orion/gpio.c new file mode 100644 index 000000000000..d5f00c86d616 --- /dev/null +++ b/arch/arm/mach-orion/gpio.c @@ -0,0 +1,225 @@ +/* + * arch/arm/mach-orion/gpio.c + * + * GPIO functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/bitops.h> +#include <asm/gpio.h> +#include <asm/arch/orion.h> +#include "common.h" + +static DEFINE_SPINLOCK(gpio_lock); +static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; +static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ + +void __init orion_gpio_set_valid_pins(u32 pins) +{ + gpio_valid[0] = pins; +} + +/* + * GENERIC_GPIO primitives + */ +int gpio_direction_input(unsigned pin) +{ + unsigned long flags; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might have not used the gpio_request(), + * so flag this pin as requested now. + */ + if (!gpio_label[pin]) + gpio_label[pin] = "?"; + + orion_setbits(GPIO_IO_CONF, 1 << pin); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned pin, int value) +{ + unsigned long flags; + int mask; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might have not used the gpio_request(), + * so flag this pin as requested now. + */ + if (!gpio_label[pin]) + gpio_label[pin] = "?"; + + mask = 1 << pin; + orion_clrbits(GPIO_BLINK_EN, mask); + if (value) + orion_setbits(GPIO_OUT, mask); + else + orion_clrbits(GPIO_OUT, mask); + orion_clrbits(GPIO_IO_CONF, mask); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned pin) +{ + int val, mask = 1 << pin; + + if (orion_read(GPIO_IO_CONF) & mask) + val = orion_read(GPIO_DATA_IN) ^ orion_read(GPIO_IN_POL); + else + val = orion_read(GPIO_OUT); + + return val & mask; +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned pin, int value) +{ + unsigned long flags; + int mask = 1 << pin; + + spin_lock_irqsave(&gpio_lock, flags); + + orion_clrbits(GPIO_BLINK_EN, mask); + if (value) + orion_setbits(GPIO_OUT, mask); + else + orion_clrbits(GPIO_OUT, mask); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(gpio_set_value); + +void orion_gpio_set_blink(unsigned pin, int blink) +{ + unsigned long flags; + int mask = 1 << pin; + + spin_lock_irqsave(&gpio_lock, flags); + + orion_clrbits(GPIO_OUT, mask); + if (blink) + orion_setbits(GPIO_BLINK_EN, mask); + else + orion_clrbits(GPIO_BLINK_EN, mask); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(orion_gpio_set_blink); + +int gpio_request(unsigned pin, const char *label) +{ + int ret = 0; + unsigned long flags; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + if (gpio_label[pin]) { + pr_debug("%s: GPIO %d already used as %s\n", + __FUNCTION__, pin, gpio_label[pin]); + ret = -EBUSY; + } else + gpio_label[pin] = label ? label : "?"; + + spin_unlock_irqrestore(&gpio_lock, flags); + return ret; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned pin) +{ + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return; + } + + if (!gpio_label[pin]) + pr_warning("%s: GPIO %d already freed\n", __FUNCTION__, pin); + else + gpio_label[pin] = NULL; +} +EXPORT_SYMBOL(gpio_free); + +/* Debug helper */ +void gpio_display(void) +{ + int i; + + for (i = 0; i < GPIO_MAX; i++) { + printk(KERN_DEBUG "Pin-%d: ", i); + + if (!test_bit(i, gpio_valid)) { + printk("non-GPIO\n"); + } else if (!gpio_label[i]) { + printk("GPIO, free\n"); + } else { + printk("GPIO, used by %s, ", gpio_label[i]); + if (orion_read(GPIO_IO_CONF) & (1 << i)) { + printk("input, active %s, level %s, edge %s\n", + ((orion_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high", + ((orion_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked", + ((orion_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked"); + } else { + printk("output, val=%d\n", (orion_read(GPIO_OUT) >> i) & 1); + } + } + } + + printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n", + MPP_0_7_CTRL, orion_read(MPP_0_7_CTRL)); + printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n", + MPP_8_15_CTRL, orion_read(MPP_8_15_CTRL)); + printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n", + MPP_16_19_CTRL, orion_read(MPP_16_19_CTRL)); + printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n", + MPP_DEV_CTRL, orion_read(MPP_DEV_CTRL)); + printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n", + GPIO_OUT, orion_read(GPIO_OUT)); + printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n", + GPIO_IO_CONF, orion_read(GPIO_IO_CONF)); + printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n", + GPIO_BLINK_EN, orion_read(GPIO_BLINK_EN)); + printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n", + GPIO_IN_POL, orion_read(GPIO_IN_POL)); + printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n", + GPIO_DATA_IN, orion_read(GPIO_DATA_IN)); + printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n", + GPIO_LEVEL_MASK, orion_read(GPIO_LEVEL_MASK)); + printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n", + GPIO_EDGE_CAUSE, orion_read(GPIO_EDGE_CAUSE)); + printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n", + GPIO_EDGE_MASK, orion_read(GPIO_EDGE_MASK)); +} diff --git a/arch/arm/mach-orion/irq.c b/arch/arm/mach-orion/irq.c new file mode 100644 index 000000000000..df7e12ad378b --- /dev/null +++ b/arch/arm/mach-orion/irq.c @@ -0,0 +1,241 @@ +/* + * arch/arm/mach-orion/irq.c + * + * Core IRQ functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <asm/gpio.h> +#include <asm/arch/orion.h> +#include "common.h" + +/***************************************************************************** + * Orion GPIO IRQ + * + * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same + * value of the line or the opposite value. + * + * Level IRQ handlers: DATA_IN is used directly as cause register. + * Interrupt are masked by LEVEL_MASK registers. + * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. + * Interrupt are masked by EDGE_MASK registers. + * Both-edge handlers: Similar to regular Edge handlers, but also swaps + * the polarity to catch the next line transaction. + * This is a race condition that might not perfectly + * work on some use cases. + * + * Every eight GPIO lines are grouped (OR'ed) before going up to main + * cause register. + * + * EDGE cause mask + * data-in /--------| |-----| |----\ + * -----| |----- ---- to main cause reg + * X \----------------| |----/ + * polarity LEVEL mask + * + ****************************************************************************/ +static void orion_gpio_irq_ack(u32 irq) +{ + int pin = irq_to_gpio(irq); + if (irq_desc[irq].status & IRQ_LEVEL) + /* + * Mask bit for level interrupt + */ + orion_clrbits(GPIO_LEVEL_MASK, 1 << pin); + else + /* + * Clear casue bit for egde interrupt + */ + orion_clrbits(GPIO_EDGE_CAUSE, 1 << pin); +} + +static void orion_gpio_irq_mask(u32 irq) +{ + int pin = irq_to_gpio(irq); + if (irq_desc[irq].status & IRQ_LEVEL) + orion_clrbits(GPIO_LEVEL_MASK, 1 << pin); + else + orion_clrbits(GPIO_EDGE_MASK, 1 << pin); +} + +static void orion_gpio_irq_unmask(u32 irq) +{ + int pin = irq_to_gpio(irq); + if (irq_desc[irq].status & IRQ_LEVEL) + orion_setbits(GPIO_LEVEL_MASK, 1 << pin); + else + orion_setbits(GPIO_EDGE_MASK, 1 << pin); +} + +static int orion_gpio_set_irq_type(u32 irq, u32 type) +{ + int pin = irq_to_gpio(irq); + struct irq_desc *desc; + + if ((orion_read(GPIO_IO_CONF) & (1 << pin)) == 0) { + printk(KERN_ERR "orion_gpio_set_irq_type failed " + "(irq %d, pin %d).\n", irq, pin); + return -EINVAL; + } + + desc = irq_desc + irq; + + switch (type) { + case IRQT_HIGH: + desc->handle_irq = handle_level_irq; + desc->status |= IRQ_LEVEL; + orion_clrbits(GPIO_IN_POL, (1 << pin)); + break; + case IRQT_LOW: + desc->handle_irq = handle_level_irq; + desc->status |= IRQ_LEVEL; + orion_setbits(GPIO_IN_POL, (1 << pin)); + break; + case IRQT_RISING: + desc->handle_irq = handle_edge_irq; + desc->status &= ~IRQ_LEVEL; + orion_clrbits(GPIO_IN_POL, (1 << pin)); + break; + case IRQT_FALLING: + desc->handle_irq = handle_edge_irq; + desc->status &= ~IRQ_LEVEL; + orion_setbits(GPIO_IN_POL, (1 << pin)); + break; + case IRQT_BOTHEDGE: + desc->handle_irq = handle_edge_irq; + desc->status &= ~IRQ_LEVEL; + /* + * set initial polarity based on current input level + */ + if ((orion_read(GPIO_IN_POL) ^ orion_read(GPIO_DATA_IN)) + & (1 << pin)) + orion_setbits(GPIO_IN_POL, (1 << pin)); /* falling */ + else + orion_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */ + + break; + default: + printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type); + return -EINVAL; + } + + desc->status &= ~IRQ_TYPE_SENSE_MASK; + desc->status |= type & IRQ_TYPE_SENSE_MASK; + + return 0; +} + +static struct irq_chip orion_gpio_irq_chip = { + .name = "Orion-IRQ-GPIO", + .ack = orion_gpio_irq_ack, + .mask = orion_gpio_irq_mask, + .unmask = orion_gpio_irq_unmask, + .set_type = orion_gpio_set_irq_type, +}; + +static void orion_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + u32 cause, offs, pin; + + BUG_ON(irq < IRQ_ORION_GPIO_0_7 || irq > IRQ_ORION_GPIO_24_31); + offs = (irq - IRQ_ORION_GPIO_0_7) * 8; + cause = (orion_read(GPIO_DATA_IN) & orion_read(GPIO_LEVEL_MASK)) | + (orion_read(GPIO_EDGE_CAUSE) & orion_read(GPIO_EDGE_MASK)); + + for (pin = offs; pin < offs + 8; pin++) { + if (cause & (1 << pin)) { + irq = gpio_to_irq(pin); + desc = irq_desc + irq; + if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) { + /* Swap polarity (race with GPIO line) */ + u32 polarity = orion_read(GPIO_IN_POL); + polarity ^= 1 << pin; + orion_write(GPIO_IN_POL, polarity); + } + desc_handle_irq(irq, desc); + } + } +} + +static void __init orion_init_gpio_irq(void) +{ + int i; + struct irq_desc *desc; + + /* + * Mask and clear GPIO IRQ interrupts + */ + orion_write(GPIO_LEVEL_MASK, 0x0); + orion_write(GPIO_EDGE_MASK, 0x0); + orion_write(GPIO_EDGE_CAUSE, 0x0); + + /* + * Register chained level handlers for GPIO IRQs by default. + * User can use set_type() if he wants to use edge types handlers. + */ + for (i = IRQ_ORION_GPIO_START; i < NR_IRQS; i++) { + set_irq_chip(i, &orion_gpio_irq_chip); + set_irq_handler(i, handle_level_irq); + desc = irq_desc + i; + desc->status |= IRQ_LEVEL; + set_irq_flags(i, IRQF_VALID); + } + set_irq_chained_handler(IRQ_ORION_GPIO_0_7, orion_gpio_irq_handler); + set_irq_chained_handler(IRQ_ORION_GPIO_8_15, orion_gpio_irq_handler); + set_irq_chained_handler(IRQ_ORION_GPIO_16_23, orion_gpio_irq_handler); + set_irq_chained_handler(IRQ_ORION_GPIO_24_31, orion_gpio_irq_handler); +} + +/***************************************************************************** + * Orion Main IRQ + ****************************************************************************/ +static void orion_main_irq_mask(u32 irq) +{ + orion_clrbits(MAIN_IRQ_MASK, 1 << irq); +} + +static void orion_main_irq_unmask(u32 irq) +{ + orion_setbits(MAIN_IRQ_MASK, 1 << irq); +} + +static struct irq_chip orion_main_irq_chip = { + .name = "Orion-IRQ-Main", + .ack = orion_main_irq_mask, + .mask = orion_main_irq_mask, + .unmask = orion_main_irq_unmask, +}; + +static void __init orion_init_main_irq(void) +{ + int i; + + /* + * Mask and clear Main IRQ interrupts + */ + orion_write(MAIN_IRQ_MASK, 0x0); + orion_write(MAIN_IRQ_CAUSE, 0x0); + + /* + * Register level handler for Main IRQs + */ + for (i = 0; i < IRQ_ORION_GPIO_START; i++) { + set_irq_chip(i, &orion_main_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + } +} + +void __init orion_init_irq(void) +{ + orion_init_main_irq(); + orion_init_gpio_irq(); +} diff --git a/arch/arm/mach-orion/kurobox_pro-setup.c b/arch/arm/mach-orion/kurobox_pro-setup.c new file mode 100644 index 000000000000..2d812ed6b5c7 --- /dev/null +++ b/arch/arm/mach-orion/kurobox_pro-setup.c @@ -0,0 +1,234 @@ +/* + * arch/arm/mach-orion/kurobox_pro-setup.c + * + * Maintainer: Ronen Shitrit <rshitrit@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/nand.h> +#include <linux/mv643xx_eth.h> +#include <linux/i2c.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <asm/arch/orion.h> +#include <asm/arch/platform.h> +#include "common.h" + +/***************************************************************************** + * KUROBOX-PRO Info + ****************************************************************************/ + +/* + * 256K NOR flash Device bus boot chip select + */ + +#define KUROBOX_PRO_NOR_BOOT_BASE 0xf4000000 +#define KUROBOX_PRO_NOR_BOOT_SIZE SZ_256K + +/* + * 256M NAND flash on Device bus chip select 1 + */ + +#define KUROBOX_PRO_NAND_BASE 0xfc000000 +#define KUROBOX_PRO_NAND_SIZE SZ_2M + +/***************************************************************************** + * 256MB NAND Flash on Device bus CS0 + ****************************************************************************/ + +static struct mtd_partition kurobox_pro_nand_parts[] = { + { + .name = "uImage", + .offset = 0, + .size = SZ_4M, + }, + { + .name = "rootfs", + .offset = SZ_4M, + .size = SZ_64M, + }, + { + .name = "extra", + .offset = SZ_4M + SZ_64M, + .size = SZ_256M - (SZ_4M + SZ_64M), + }, +}; + +static struct resource kurobox_pro_nand_resource = { + .flags = IORESOURCE_MEM, + .start = KUROBOX_PRO_NAND_BASE, + .end = KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1, +}; + +static struct orion_nand_data kurobox_pro_nand_data = { + .parts = kurobox_pro_nand_parts, + .nr_parts = ARRAY_SIZE(kurobox_pro_nand_parts), + .cle = 0, + .ale = 1, + .width = 8, +}; + +static struct platform_device kurobox_pro_nand_flash = { + .name = "orion_nand", + .id = -1, + .dev = { + .platform_data = &kurobox_pro_nand_data, + }, + .resource = &kurobox_pro_nand_resource, + .num_resources = 1, +}; + +/***************************************************************************** + * 256KB NOR Flash on BOOT Device + ****************************************************************************/ + +static struct physmap_flash_data kurobox_pro_nor_flash_data = { + .width = 1, +}; + +static struct resource kurobox_pro_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = KUROBOX_PRO_NOR_BOOT_BASE, + .end = KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device kurobox_pro_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &kurobox_pro_nor_flash_data, + }, + .num_resources = 1, + .resource = &kurobox_pro_nor_flash_resource, +}; + +/***************************************************************************** + * PCI + ****************************************************************************/ + +static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* + * PCI isn't used on the Kuro + */ + if (dev->bus->number == orion_pcie_local_bus_nr()) + return IRQ_ORION_PCIE0_INT; + else + printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n"); + + return -1; +} + +static struct hw_pci kurobox_pro_pci __initdata = { + .nr_controllers = 1, + .swizzle = pci_std_swizzle, + .setup = orion_pci_sys_setup, + .scan = orion_pci_sys_scan_bus, + .map_irq = kurobox_pro_pci_map_irq, +}; + +static int __init kurobox_pro_pci_init(void) +{ + if (machine_is_kurobox_pro()) + pci_common_init(&kurobox_pro_pci); + + return 0; +} + +subsys_initcall(kurobox_pro_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/***************************************************************************** + * RTC 5C372a on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = { + .driver_name = "rtc-rs5c372", + .type = "rs5c372a", + .addr = 0x32, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct platform_device *kurobox_pro_devices[] __initdata = { + &kurobox_pro_nor_flash, + &kurobox_pro_nand_flash, +}; + +static void __init kurobox_pro_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion_init(); + + /* + * Setup the CPU address decode windows for our devices + */ + orion_setup_cpu_win(ORION_DEV_BOOT, KUROBOX_PRO_NOR_BOOT_BASE, + KUROBOX_PRO_NOR_BOOT_SIZE, -1); + orion_setup_cpu_win(ORION_DEV0, KUROBOX_PRO_NAND_BASE, + KUROBOX_PRO_NAND_SIZE, -1); + /* + * Open a special address decode windows for the PCIE WA. + */ + orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE); + orion_write(ORION_REGS_BASE | 0x20070, (0x7941 | + (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16)); + + /* + * Setup Multiplexing Pins -- + * MPP[0-1] Not used + * MPP[2] GPIO Micon + * MPP[3] GPIO RTC + * MPP[4-5] Not used + * MPP[6] Nand Flash REn + * MPP[7] Nand Flash WEn + * MPP[8-11] Not used + * MPP[12] SATA 0 presence Indication + * MPP[13] SATA 1 presence Indication + * MPP[14] SATA 0 active Indication + * MPP[15] SATA 1 active indication + * MPP[16-19] Not used + */ + orion_write(MPP_0_7_CTRL, 0x44220003); + orion_write(MPP_8_15_CTRL, 0x55550000); + orion_write(MPP_16_19_CTRL, 0x0); + + orion_gpio_set_valid_pins(0x0000000c); + + platform_add_devices(kurobox_pro_devices, ARRAY_SIZE(kurobox_pro_devices)); + i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1); + orion_eth_init(&kurobox_pro_eth_data); +} + +MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro") + /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */ + .phys_io = ORION_REGS_BASE, + .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = kurobox_pro_init, + .map_io = orion_map_io, + .init_irq = orion_init_irq, + .timer = &orion_timer, +MACHINE_END diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c new file mode 100644 index 000000000000..0498d7c69b30 --- /dev/null +++ b/arch/arm/mach-orion/pci.c @@ -0,0 +1,557 @@ +/* + * arch/arm/mach-orion/pci.c + * + * PCI and PCIE functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/pci.h> +#include <asm/mach/pci.h> +#include "common.h" + +/***************************************************************************** + * Orion has one PCIE controller and one PCI controller. + * + * Note1: The local PCIE bus number is '0'. The local PCI bus number + * follows the scanned PCIE bridged busses, if any. + * + * Note2: It is possible for PCI/PCIE agents to access many subsystem's + * space, by configuring BARs and Address Decode Windows, e.g. flashes on + * device bus, Orion registers, etc. However this code only enable the + * access to DDR banks. + ****************************************************************************/ + + +/***************************************************************************** + * PCIE controller + ****************************************************************************/ +#define PCIE_CTRL ORION_PCIE_REG(0x1a00) +#define PCIE_STAT ORION_PCIE_REG(0x1a04) +#define PCIE_DEV_ID ORION_PCIE_REG(0x0000) +#define PCIE_CMD_STAT ORION_PCIE_REG(0x0004) +#define PCIE_DEV_REV ORION_PCIE_REG(0x0008) +#define PCIE_MASK ORION_PCIE_REG(0x1910) +#define PCIE_CONF_ADDR ORION_PCIE_REG(0x18f8) +#define PCIE_CONF_DATA ORION_PCIE_REG(0x18fc) + +/* + * PCIE_STAT bits + */ +#define PCIE_STAT_LINK_DOWN 1 +#define PCIE_STAT_BUS_OFFS 8 +#define PCIE_STAT_BUS_MASK (0xff << PCIE_STAT_BUS_OFFS) +#define PCIE_STAT_DEV_OFFS 20 +#define PCIE_STAT_DEV_MASK (0x1f << PCIE_STAT_DEV_OFFS) + +/* + * PCIE_CONF_ADDR bits + */ +#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 24) | ((r) & 0xfc)) +#define PCIE_CONF_FUNC(f) (((f) & 0x3) << 8) +#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11) +#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16) +#define PCIE_CONF_ADDR_EN (1 << 31) + +/* + * PCIE config cycles are done by programming the PCIE_CONF_ADDR register + * and then reading the PCIE_CONF_DATA register. Need to make sure these + * transactions are atomic. + */ +static DEFINE_SPINLOCK(orion_pcie_lock); + +void orion_pcie_id(u32 *dev, u32 *rev) +{ + *dev = orion_read(PCIE_DEV_ID) >> 16; + *rev = orion_read(PCIE_DEV_REV) & 0xff; +} + +u32 orion_pcie_local_bus_nr(void) +{ + u32 stat = orion_read(PCIE_STAT); + return((stat & PCIE_STAT_BUS_MASK) >> PCIE_STAT_BUS_OFFS); +} + +static u32 orion_pcie_local_dev_nr(void) +{ + u32 stat = orion_read(PCIE_STAT); + return((stat & PCIE_STAT_DEV_MASK) >> PCIE_STAT_DEV_OFFS); +} + +static u32 orion_pcie_no_link(void) +{ + u32 stat = orion_read(PCIE_STAT); + return(stat & PCIE_STAT_LINK_DOWN); +} + +static void orion_pcie_set_bus_nr(int nr) +{ + orion_clrbits(PCIE_STAT, PCIE_STAT_BUS_MASK); + orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS); +} + +static void orion_pcie_master_slave_enable(void) +{ + orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER | + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY); +} + +static void orion_pcie_enable_interrupts(void) +{ + /* + * Enable interrupts lines + * INTA[24] INTB[25] INTC[26] INTD[27] + */ + orion_setbits(PCIE_MASK, 0xf<<24); +} + +static int orion_pcie_valid_config(u32 bus, u32 dev) +{ + /* + * Don't go out when trying to access -- + * 1. our own device + * 2. where there's no device connected (no link) + * 3. nonexisting devices on local bus + */ + + if ((orion_pcie_local_bus_nr() == bus) && + (orion_pcie_local_dev_nr() == dev)) + return 0; + + if (orion_pcie_no_link()) + return 0; + + if (bus == orion_pcie_local_bus_nr()) + if (((orion_pcie_local_dev_nr() == 0) && (dev != 1)) || + ((orion_pcie_local_dev_nr() != 0) && (dev != 0))) + return 0; + + return 1; +} + +static int orion_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, + int size, u32 *val) +{ + unsigned long flags; + unsigned int dev, rev, pcie_addr; + + if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + spin_lock_irqsave(&orion_pcie_lock, flags); + + orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN); + + orion_pcie_id(&dev, &rev); + if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) { + /* extended register space */ + pcie_addr = ORION_PCIE_WA_BASE; + pcie_addr |= PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where); + *val = orion_read(pcie_addr); + } else + *val = orion_read(PCIE_CONF_DATA); + + if (size == 1) + *val = (*val >> (8*(where & 0x3))) & 0xff; + else if (size == 2) + *val = (*val >> (8*(where & 0x3))) & 0xffff; + + spin_unlock_irqrestore(&orion_pcie_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + + +static int orion_pcie_wr_conf(struct pci_bus *bus, u32 devfn, int where, + int size, u32 val) +{ + unsigned long flags; + int ret; + + if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + spin_lock_irqsave(&orion_pcie_lock, flags); + + ret = PCIBIOS_SUCCESSFUL; + + orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN); + + if (size == 4) { + __raw_writel(val, PCIE_CONF_DATA); + } else if (size == 2) { + __raw_writew(val, PCIE_CONF_DATA + (where & 0x3)); + } else if (size == 1) { + __raw_writeb(val, PCIE_CONF_DATA + (where & 0x3)); + } else { + ret = PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&orion_pcie_lock, flags); + + return ret; +} + +struct pci_ops orion_pcie_ops = { + .read = orion_pcie_rd_conf, + .write = orion_pcie_wr_conf, +}; + + +static int orion_pcie_setup(struct pci_sys_data *sys) +{ + struct resource *res; + + /* + * Master + Slave enable + */ + orion_pcie_master_slave_enable(); + + /* + * Enable interrupts lines A-D + */ + orion_pcie_enable_interrupts(); + + /* + * Request resource + */ + res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); + if (!res) + panic("orion_pci_setup unable to alloc resources"); + + /* + * IORESOURCE_IO + */ + res[0].name = "PCI-EX I/O Space"; + res[0].flags = IORESOURCE_IO; + res[0].start = ORION_PCIE_IO_REMAP; + res[0].end = res[0].start + ORION_PCIE_IO_SIZE - 1; + if (request_resource(&ioport_resource, &res[0])) + panic("Request PCIE IO resource failed\n"); + sys->resource[0] = &res[0]; + + /* + * IORESOURCE_MEM + */ + res[1].name = "PCI-EX Memory Space"; + res[1].flags = IORESOURCE_MEM; + res[1].start = ORION_PCIE_MEM_BASE; + res[1].end = res[1].start + ORION_PCIE_MEM_SIZE - 1; + if (request_resource(&iomem_resource, &res[1])) + panic("Request PCIE Memory resource failed\n"); + sys->resource[1] = &res[1]; + + sys->resource[2] = NULL; + sys->io_offset = 0; + + return 1; +} + +/***************************************************************************** + * PCI controller + ****************************************************************************/ +#define PCI_MODE ORION_PCI_REG(0xd00) +#define PCI_CMD ORION_PCI_REG(0xc00) +#define PCI_P2P_CONF ORION_PCI_REG(0x1d14) +#define PCI_CONF_ADDR ORION_PCI_REG(0xc78) +#define PCI_CONF_DATA ORION_PCI_REG(0xc7c) + +/* + * PCI_MODE bits + */ +#define PCI_MODE_64BIT (1 << 2) +#define PCI_MODE_PCIX ((1 << 4) | (1 << 5)) + +/* + * PCI_CMD bits + */ +#define PCI_CMD_HOST_REORDER (1 << 29) + +/* + * PCI_P2P_CONF bits + */ +#define PCI_P2P_BUS_OFFS 16 +#define PCI_P2P_BUS_MASK (0xff << PCI_P2P_BUS_OFFS) +#define PCI_P2P_DEV_OFFS 24 +#define PCI_P2P_DEV_MASK (0x1f << PCI_P2P_DEV_OFFS) + +/* + * PCI_CONF_ADDR bits + */ +#define PCI_CONF_REG(reg) ((reg) & 0xfc) +#define PCI_CONF_FUNC(func) (((func) & 0x3) << 8) +#define PCI_CONF_DEV(dev) (((dev) & 0x1f) << 11) +#define PCI_CONF_BUS(bus) (((bus) & 0xff) << 16) +#define PCI_CONF_ADDR_EN (1 << 31) + +/* + * Internal configuration space + */ +#define PCI_CONF_FUNC_STAT_CMD 0 +#define PCI_CONF_REG_STAT_CMD 4 +#define PCIX_STAT 0x64 +#define PCIX_STAT_BUS_OFFS 8 +#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS) + +/* + * PCI config cycles are done by programming the PCI_CONF_ADDR register + * and then reading the PCI_CONF_DATA register. Need to make sure these + * transactions are atomic. + */ +static DEFINE_SPINLOCK(orion_pci_lock); + +u32 orion_pci_local_bus_nr(void) +{ + u32 conf = orion_read(PCI_P2P_CONF); + return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); +} + +u32 orion_pci_local_dev_nr(void) +{ + u32 conf = orion_read(PCI_P2P_CONF); + return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS); +} + +int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, + u32 where, u32 size, u32 *val) +{ + unsigned long flags; + spin_lock_irqsave(&orion_pci_lock, flags); + + orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) | + PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | + PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN); + + *val = orion_read(PCI_CONF_DATA); + + if (size == 1) + *val = (*val >> (8*(where & 0x3))) & 0xff; + else if (size == 2) + *val = (*val >> (8*(where & 0x3))) & 0xffff; + + spin_unlock_irqrestore(&orion_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, + u32 where, u32 size, u32 val) +{ + unsigned long flags; + int ret = PCIBIOS_SUCCESSFUL; + + spin_lock_irqsave(&orion_pci_lock, flags); + + orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) | + PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | + PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN); + + if (size == 4) { + __raw_writel(val, PCI_CONF_DATA); + } else if (size == 2) { + __raw_writew(val, PCI_CONF_DATA + (where & 0x3)); + } else if (size == 1) { + __raw_writeb(val, PCI_CONF_DATA + (where & 0x3)); + } else { + ret = PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&orion_pci_lock, flags); + + return ret; +} + +static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 *val) +{ + /* + * Don't go out for local device + */ + if ((orion_pci_local_bus_nr() == bus->number) && + (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return orion_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where, size, val); +} + +static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 val) +{ + /* + * Don't go out for local device + */ + if ((orion_pci_local_bus_nr() == bus->number) && + (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) + return PCIBIOS_DEVICE_NOT_FOUND; + + return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where, size, val); +} + +struct pci_ops orion_pci_ops = { + .read = orion_pci_rd_conf, + .write = orion_pci_wr_conf, +}; + +static void orion_pci_set_bus_nr(int nr) +{ + u32 p2p = orion_read(PCI_P2P_CONF); + + if (orion_read(PCI_MODE) & PCI_MODE_PCIX) { + /* + * PCI-X mode + */ + u32 pcix_status, bus, dev; + bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS; + dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS; + orion_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status); + pcix_status &= ~PCIX_STAT_BUS_MASK; + pcix_status |= (nr << PCIX_STAT_BUS_OFFS); + orion_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status); + } else { + /* + * PCI Conventional mode + */ + p2p &= ~PCI_P2P_BUS_MASK; + p2p |= (nr << PCI_P2P_BUS_OFFS); + orion_write(PCI_P2P_CONF, p2p); + } +} + +static void orion_pci_master_slave_enable(void) +{ + u32 bus_nr, dev_nr, func, reg, val; + + bus_nr = orion_pci_local_bus_nr(); + dev_nr = orion_pci_local_dev_nr(); + func = PCI_CONF_FUNC_STAT_CMD; + reg = PCI_CONF_REG_STAT_CMD; + orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val); + val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7); +} + +static int orion_pci_setup(struct pci_sys_data *sys) +{ + struct resource *res; + + /* + * Master + Slave enable + */ + orion_pci_master_slave_enable(); + + /* + * Force ordering + */ + orion_setbits(PCI_CMD, PCI_CMD_HOST_REORDER); + + /* + * Request resources + */ + res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); + if (!res) + panic("orion_pci_setup unable to alloc resources"); + + /* + * IORESOURCE_IO + */ + res[0].name = "PCI I/O Space"; + res[0].flags = IORESOURCE_IO; + res[0].start = ORION_PCI_IO_REMAP; + res[0].end = res[0].start + ORION_PCI_IO_SIZE - 1; + if (request_resource(&ioport_resource, &res[0])) + panic("Request PCI IO resource failed\n"); + sys->resource[0] = &res[0]; + + /* + * IORESOURCE_MEM + */ + res[1].name = "PCI Memory Space"; + res[1].flags = IORESOURCE_MEM; + res[1].start = ORION_PCI_MEM_BASE; + res[1].end = res[1].start + ORION_PCI_MEM_SIZE - 1; + if (request_resource(&iomem_resource, &res[1])) + panic("Request PCI Memory resource failed\n"); + sys->resource[1] = &res[1]; + + sys->resource[2] = NULL; + sys->io_offset = 0; + + return 1; +} + + +/***************************************************************************** + * General PCIE + PCI + ****************************************************************************/ +int orion_pci_sys_setup(int nr, struct pci_sys_data *sys) +{ + int ret = 0; + + if (nr == 0) { + /* + * PCIE setup + */ + orion_pcie_set_bus_nr(0); + ret = orion_pcie_setup(sys); + } else if (nr == 1) { + /* + * PCI setup + */ + ret = orion_pci_setup(sys); + } + + return ret; +} + +struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys) +{ + struct pci_ops *ops; + struct pci_bus *bus; + + + if (nr == 0) { + u32 pci_bus; + /* + * PCIE scan + */ + ops = &orion_pcie_ops; + bus = pci_scan_bus(sys->busnr, ops, sys); + /* + * Set local PCI bus number to follow PCIE bridges (if any) + */ + pci_bus = bus->number + bus->subordinate - bus->secondary + 1; + orion_pci_set_bus_nr(pci_bus); + } else if (nr == 1) { + /* + * PCI scan + */ + ops = &orion_pci_ops; + bus = pci_scan_bus(sys->busnr, ops, sys); + } else { + BUG(); + bus = NULL; + } + + return bus; +} diff --git a/arch/arm/mach-orion/rd88f5182-setup.c b/arch/arm/mach-orion/rd88f5182-setup.c new file mode 100644 index 000000000000..026d74325d01 --- /dev/null +++ b/arch/arm/mach-orion/rd88f5182-setup.c @@ -0,0 +1,306 @@ +/* + * arch/arm/mach-orion/rd88f5182-setup.c + * + * Marvell Orion-NAS Reference Design Setup + * + * Maintainer: Ronen Shitrit <rshitrit@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/i2c.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/leds.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <asm/arch/orion.h> +#include <asm/arch/platform.h> +#include "common.h" + +/***************************************************************************** + * RD-88F5182 Info + ****************************************************************************/ + +/* + * 512K NOR flash Device bus boot chip select + */ + +#define RD88F5182_NOR_BOOT_BASE 0xf4000000 +#define RD88F5182_NOR_BOOT_SIZE SZ_512K + +/* + * 16M NOR flash on Device bus chip select 1 + */ + +#define RD88F5182_NOR_BASE 0xfc000000 +#define RD88F5182_NOR_SIZE SZ_16M + +/* + * PCI + */ + +#define RD88F5182_PCI_SLOT0_OFFS 7 +#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7 +#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6 + +/* + * GPIO Debug LED + */ + +#define RD88F5182_GPIO_DBG_LED 0 + +/***************************************************************************** + * 16M NOR Flash on Device bus CS1 + ****************************************************************************/ + +static struct physmap_flash_data rd88f5182_nor_flash_data = { + .width = 1, +}; + +static struct resource rd88f5182_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = RD88F5182_NOR_BASE, + .end = RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1, +}; + +static struct platform_device rd88f5182_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &rd88f5182_nor_flash_data, + }, + .num_resources = 1, + .resource = &rd88f5182_nor_flash_resource, +}; + +#ifdef CONFIG_LEDS + +/***************************************************************************** + * Use GPIO debug led as CPU active indication + ****************************************************************************/ + +static void rd88f5182_dbgled_event(led_event_t evt) +{ + int val; + + if (evt == led_idle_end) + val = 1; + else if (evt == led_idle_start) + val = 0; + else + return; + + gpio_set_value(RD88F5182_GPIO_DBG_LED, val); +} + +static int __init rd88f5182_dbgled_init(void) +{ + int pin; + + if (machine_is_rd88f5182()) { + pin = RD88F5182_GPIO_DBG_LED; + + if (gpio_request(pin, "DBGLED") == 0) { + if (gpio_direction_output(pin, 0) != 0) { + printk(KERN_ERR "rd88f5182_dbgled_init failed " + "to set output pin %d\n", pin); + gpio_free(pin); + return 0; + } + } else { + printk(KERN_ERR "rd88f5182_dbgled_init failed " + "to request gpio %d\n", pin); + return 0; + } + + leds_event = rd88f5182_dbgled_event; + } + return 0; +} + +__initcall(rd88f5182_dbgled_init); + +#endif + +/***************************************************************************** + * PCI + ****************************************************************************/ + +void __init rd88f5182_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN; + if (gpio_request(pin, "PCI IntA") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "rd88f5182_pci_preinit faield to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin); + } + + pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN; + if (gpio_request(pin, "PCI IntB") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "rd88f5182_pci_preinit faield to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin); + } +} + +static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* + * PCI-E isn't used on the RD2 + */ + if (dev->bus->number == orion_pcie_local_bus_nr()) + return IRQ_ORION_PCIE0_INT; + + /* + * PCI IRQs are connected via GPIOs + */ + switch (slot - RD88F5182_PCI_SLOT0_OFFS) { + case 0: + if (pin == 1) + return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN); + else + return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN); + default: + return -1; + } +} + +static struct hw_pci rd88f5182_pci __initdata = { + .nr_controllers = 2, + .preinit = rd88f5182_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = orion_pci_sys_setup, + .scan = orion_pci_sys_scan_bus, + .map_irq = rd88f5182_pci_map_irq, +}; + +static int __init rd88f5182_pci_init(void) +{ + if (machine_is_rd88f5182()) + pci_common_init(&rd88f5182_pci); + + return 0; +} + +subsys_initcall(rd88f5182_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data rd88f5182_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/***************************************************************************** + * RTC DS1338 on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata rd88f5182_i2c_rtc = { + .driver_name = "rtc-ds1307", + .type = "ds1338", + .addr = 0x68, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct platform_device *rd88f5182_devices[] __initdata = { + &rd88f5182_nor_flash, +}; + +static void __init rd88f5182_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion_init(); + + /* + * Setup the CPU address decode windows for our devices + */ + orion_setup_cpu_win(ORION_DEV_BOOT, RD88F5182_NOR_BOOT_BASE, + RD88F5182_NOR_BOOT_SIZE, -1); + orion_setup_cpu_win(ORION_DEV1, RD88F5182_NOR_BASE, + RD88F5182_NOR_SIZE, -1); + + /* + * Open a special address decode windows for the PCIE WA. + */ + orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE); + orion_write(ORION_REGS_BASE | 0x20070, (0x7941 | + (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16)); + + /* + * Setup Multiplexing Pins -- + * MPP[0] Debug Led (GPIO - Out) + * MPP[1] Debug Led (GPIO - Out) + * MPP[2] N/A + * MPP[3] RTC_Int (GPIO - In) + * MPP[4] GPIO + * MPP[5] GPIO + * MPP[6] PCI_intA (GPIO - In) + * MPP[7] PCI_intB (GPIO - In) + * MPP[8-11] N/A + * MPP[12] SATA 0 presence Indication + * MPP[13] SATA 1 presence Indication + * MPP[14] SATA 0 active Indication + * MPP[15] SATA 1 active indication + * MPP[16-19] Not used + * MPP[20] PCI Clock to MV88F5182 + * MPP[21] PCI Clock to mini PCI CON11 + * MPP[22] USB 0 over current indication + * MPP[23] USB 1 over current indication + * MPP[24] USB 1 over current enable + * MPP[25] USB 0 over current enable + */ + + orion_write(MPP_0_7_CTRL, 0x00000003); + orion_write(MPP_8_15_CTRL, 0x55550000); + orion_write(MPP_16_19_CTRL, 0x5555); + + orion_gpio_set_valid_pins(0x000000fb); + + platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices)); + i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1); + orion_eth_init(&rd88f5182_eth_data); +} + +MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design") + /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */ + .phys_io = ORION_REGS_BASE, + .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = rd88f5182_init, + .map_io = orion_map_io, + .init_irq = orion_init_irq, + .timer = &orion_timer, +MACHINE_END diff --git a/arch/arm/mach-orion/time.c b/arch/arm/mach-orion/time.c new file mode 100644 index 000000000000..bd4262da4f40 --- /dev/null +++ b/arch/arm/mach-orion/time.c @@ -0,0 +1,181 @@ +/* + * arch/arm/mach-orion/time.c + * + * Core time functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein <tzachi@marvell.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <asm/mach/time.h> +#include <asm/arch/orion.h> +#include "common.h" + +/* + * Timer0: clock_event_device, Tick. + * Timer1: clocksource, Free running. + * WatchDog: Not used. + * + * Timers are counting down. + */ +#define CLOCKEVENT 0 +#define CLOCKSOURCE 1 + +/* + * Timers bits + */ +#define BRIDGE_INT_TIMER(x) (1 << ((x) + 1)) +#define TIMER_EN(x) (1 << ((x) * 2)) +#define TIMER_RELOAD_EN(x) (1 << (((x) * 2) + 1)) +#define BRIDGE_INT_TIMER_WD (1 << 3) +#define TIMER_WD_EN (1 << 4) +#define TIMER_WD_RELOAD_EN (1 << 5) + +static cycle_t orion_clksrc_read(void) +{ + return (0xffffffff - orion_read(TIMER_VAL(CLOCKSOURCE))); +} + +static struct clocksource orion_clksrc = { + .name = "orion_clocksource", + .shift = 20, + .rating = 300, + .read = orion_clksrc_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int +orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) +{ + unsigned long flags; + + if (delta == 0) + return -ETIME; + + local_irq_save(flags); + + /* + * Clear and enable timer interrupt bit + */ + orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); + + /* + * Setup new timer value + */ + orion_write(TIMER_VAL(CLOCKEVENT), delta); + + /* + * Disable auto reload and kickoff the timer + */ + orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT)); + orion_setbits(TIMER_CTRL, TIMER_EN(CLOCKEVENT)); + + local_irq_restore(flags); + + return 0; +} + +static void +orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + + if (mode == CLOCK_EVT_MODE_PERIODIC) { + /* + * Setup latch cycles in timer and enable reload interrupt. + */ + orion_write(TIMER_VAL_RELOAD(CLOCKEVENT), LATCH); + orion_write(TIMER_VAL(CLOCKEVENT), LATCH); + orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) | + TIMER_EN(CLOCKEVENT)); + } else { + /* + * Disable timer and interrupt + */ + orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) | + TIMER_EN(CLOCKEVENT)); + } + + local_irq_restore(flags); +} + +static struct clock_event_device orion_clkevt = { + .name = "orion_tick", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .rating = 300, + .cpumask = CPU_MASK_CPU0, + .set_next_event = orion_clkevt_next_event, + .set_mode = orion_clkevt_mode, +}; + +static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) +{ + /* + * Clear cause bit and do event + */ + orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_clkevt.event_handler(&orion_clkevt); + return IRQ_HANDLED; +} + +static struct irqaction orion_timer_irq = { + .name = "orion_tick", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = orion_timer_interrupt +}; + +static void orion_timer_init(void) +{ + /* + * Setup clocksource free running timer (no interrupt on reload) + */ + orion_write(TIMER_VAL(CLOCKSOURCE), 0xffffffff); + orion_write(TIMER_VAL_RELOAD(CLOCKSOURCE), 0xffffffff); + orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKSOURCE)); + orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKSOURCE) | + TIMER_EN(CLOCKSOURCE)); + + /* + * Register clocksource + */ + orion_clksrc.mult = + clocksource_hz2mult(CLOCK_TICK_RATE, orion_clksrc.shift); + + clocksource_register(&orion_clksrc); + + /* + * Connect and enable tick handler + */ + setup_irq(IRQ_ORION_BRIDGE, &orion_timer_irq); + + /* + * Register clockevent + */ + orion_clkevt.mult = + div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, orion_clkevt.shift); + orion_clkevt.max_delta_ns = + clockevent_delta2ns(0xfffffffe, &orion_clkevt); + orion_clkevt.min_delta_ns = + clockevent_delta2ns(1, &orion_clkevt); + + clockevents_register_device(&orion_clkevt); +} + +struct sys_timer orion_timer = { + .init = orion_timer_init, +}; diff --git a/arch/arm/mach-orion/ts209-setup.c b/arch/arm/mach-orion/ts209-setup.c new file mode 100644 index 000000000000..e3e930efd155 --- /dev/null +++ b/arch/arm/mach-orion/ts209-setup.c @@ -0,0 +1,335 @@ +/* + * QNAP TS-109/TS-209 Board Setup + * + * Maintainer: Byron Bradley <byron.bbradley@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/nand.h> +#include <linux/mv643xx_eth.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/serial_reg.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <asm/arch/orion.h> +#include <asm/arch/platform.h> +#include "common.h" + +#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000 +#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M + +/**************************************************************************** + * 8MiB NOR flash. The struct mtd_partition is not in the same order as the + * partitions on the device because we want to keep compatability with + * existing QNAP firmware. + * + * Layout as used by QNAP: + * [2] 0x00000000-0x00200000 : "Kernel" + * [3] 0x00200000-0x00600000 : "RootFS1" + * [4] 0x00600000-0x00700000 : "RootFS2" + * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) + * [5] 0x00760000-0x00780000 : "U-Boot Config" + * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) + ***************************************************************************/ +static struct mtd_partition qnap_ts209_partitions[] = { + { + .name = "U-Boot", + .size = 0x00080000, + .offset = 0x00780000, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "Kernel", + .size = 0x00200000, + .offset = 0, + }, { + .name = "RootFS1", + .size = 0x00400000, + .offset = 0x00200000, + }, { + .name = "RootFS2", + .size = 0x00100000, + .offset = 0x00600000, + }, { + .name = "U-Boot Config", + .size = 0x00020000, + .offset = 0x00760000, + }, { + .name = "NAS Config", + .size = 0x00060000, + .offset = 0x00700000, + .mask_flags = MTD_WRITEABLE, + } +}; + +static struct physmap_flash_data qnap_ts209_nor_flash_data = { + .width = 1, + .parts = qnap_ts209_partitions, + .nr_parts = ARRAY_SIZE(qnap_ts209_partitions) +}; + +static struct resource qnap_ts209_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = QNAP_TS209_NOR_BOOT_BASE, + .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device qnap_ts209_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { .platform_data = &qnap_ts209_nor_flash_data, }, + .resource = &qnap_ts209_nor_flash_resource, + .num_resources = 1, +}; + +/***************************************************************************** + * PCI + ****************************************************************************/ + +#define QNAP_TS209_PCI_SLOT0_OFFS 7 +#define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6 +#define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7 + +void __init qnap_ts209_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN; + if (gpio_request(pin, "PCI Int1") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "qnap_ts209_pci_preinit failed to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request " + "%d\n", pin); + } + + pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN; + if (gpio_request(pin, "PCI Int2") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "qnap_ts209_pci_preinit failed " + "to set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request " + "%d\n", pin); + } +} + +static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* + * PCIE IRQ is connected internally (not GPIO) + */ + if (dev->bus->number == orion_pcie_local_bus_nr()) + return IRQ_ORION_PCIE0_INT; + + /* + * PCI IRQs are connected via GPIOs + */ + switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) { + case 0: + return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN); + case 1: + return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN); + default: + return -1; + } +} + +static struct hw_pci qnap_ts209_pci __initdata = { + .nr_controllers = 2, + .preinit = qnap_ts209_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = orion_pci_sys_setup, + .scan = orion_pci_sys_scan_bus, + .map_irq = qnap_ts209_pci_map_irq, +}; + +static int __init qnap_ts209_pci_init(void) +{ + if (machine_is_ts_x09()) + pci_common_init(&qnap_ts209_pci); + + return 0; +} + +subsys_initcall(qnap_ts209_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data qnap_ts209_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/***************************************************************************** + * RTC S35390A on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = { + .driver_name = "rtc-s35390a", + .addr = 0x30, +}; + +/**************************************************************************** + * GPIO Attached Keys + * Power button is attached to the PIC microcontroller + ****************************************************************************/ + +#define QNAP_TS209_GPIO_KEY_MEDIA 1 +#define QNAP_TS209_GPIO_KEY_RESET 2 + +static struct gpio_keys_button qnap_ts209_buttons[] = { + { + .code = KEY_RESTART, + .gpio = QNAP_TS209_GPIO_KEY_MEDIA, + .desc = "USB Copy Button", + .active_low = 1, + }, + { + .code = KEY_POWER, + .gpio = QNAP_TS209_GPIO_KEY_RESET, + .desc = "Reset Button", + .active_low = 1, + } +}; + +static struct gpio_keys_platform_data qnap_ts209_button_data = { + .buttons = qnap_ts209_buttons, + .nbuttons = ARRAY_SIZE(qnap_ts209_buttons), +}; + +static struct platform_device qnap_ts209_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { .platform_data = &qnap_ts209_button_data, }, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct platform_device *qnap_ts209_devices[] __initdata = { + &qnap_ts209_nor_flash, + &qnap_ts209_button_device, +}; + +/* + * QNAP TS-[12]09 specific power off method via UART1-attached PIC + */ + +#define UART1_REG(x) (UART1_BASE + ((UART_##x) << 2)) + +static void qnap_ts209_power_off(void) +{ + /* 19200 baud divisor */ + const unsigned divisor = ((ORION_TCLK + (8 * 19200)) / (16 * 19200)); + + pr_info("%s: triggering power-off...\n", __func__); + + /* hijack uart1 and reset into sane state (19200,8n1) */ + orion_write(UART1_REG(LCR), 0x83); + orion_write(UART1_REG(DLL), divisor & 0xff); + orion_write(UART1_REG(DLM), (divisor >> 8) & 0xff); + orion_write(UART1_REG(LCR), 0x03); + orion_write(UART1_REG(IER), 0x00); + orion_write(UART1_REG(FCR), 0x00); + orion_write(UART1_REG(MCR), 0x00); + + /* send the power-off command 'A' to PIC */ + orion_write(UART1_REG(TX), 'A'); +} + +static void __init qnap_ts209_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion_init(); + + /* + * Setup flash mapping + */ + orion_setup_cpu_win(ORION_DEV_BOOT, QNAP_TS209_NOR_BOOT_BASE, + QNAP_TS209_NOR_BOOT_SIZE, -1); + + /* + * Open a special address decode windows for the PCIE WA. + */ + orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE); + orion_write(ORION_REGS_BASE | 0x20070, (0x7941 | + (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16)); + + /* + * Setup Multiplexing Pins -- + * MPP[0] Reserved + * MPP[1] USB copy button (0 active) + * MPP[2] Load defaults button (0 active) + * MPP[3] GPIO RTC + * MPP[4-5] Reserved + * MPP[6] PCI Int A + * MPP[7] PCI Int B + * MPP[8-11] Reserved + * MPP[12] SATA 0 presence + * MPP[13] SATA 1 presence + * MPP[14] SATA 0 active + * MPP[15] SATA 1 active + * MPP[16] UART1 RXD + * MPP[17] UART1 TXD + * MPP[18] SW_RST (0 active) + * MPP[19] Reserved + * MPP[20] PCI clock 0 + * MPP[21] PCI clock 1 + * MPP[22] USB 0 over current + * MPP[23-25] Reserved + */ + orion_write(MPP_0_7_CTRL, 0x3); + orion_write(MPP_8_15_CTRL, 0x55550000); + orion_write(MPP_16_19_CTRL, 0x5500); + orion_gpio_set_valid_pins(0x3cc0fff); + + /* register ts209 specific power-off method */ + pm_power_off = qnap_ts209_power_off; + + platform_add_devices(qnap_ts209_devices, + ARRAY_SIZE(qnap_ts209_devices)); + i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1); + orion_eth_init(&qnap_ts209_eth_data); +} + +MACHINE_START(TS209, "QNAP TS-109/TS-209") + /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */ + .phys_io = ORION_REGS_BASE, + .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = qnap_ts209_init, + .map_io = orion_map_io, + .init_irq = orion_init_irq, + .timer = &orion_timer, +MACHINE_END diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index cb104c2a7329..76348f060f27 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -342,6 +342,27 @@ config CPU_XSC3 select CPU_TLB_V4WBI if MMU select IO_36 +# Feroceon +config CPU_FEROCEON + bool + depends on ARCH_ORION + default y + select CPU_32v5 + select CPU_ABRT_EV5T + select CPU_CACHE_VIVT + select CPU_CP15_MMU + select CPU_COPY_V4WB if MMU + select CPU_TLB_V4WBI if MMU + +config CPU_FEROCEON_OLD_ID + bool "Accept early Feroceon cores with an ARM926 ID" + depends on CPU_FEROCEON && !CPU_ARM926T + default y + help + This enables the usage of some old Feroceon cores + for which the CPU ID is equal to the ARM926 ID. + Relevant for Feroceon-1850 and early Feroceon-2850. + # ARMv6 config CPU_V6 bool "Support ARM V6 processor" @@ -539,7 +560,7 @@ comment "Processor Features" config ARM_THUMB bool "Support Thumb user binaries" - 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_V6 || CPU_V7 + 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_V6 || CPU_V7 || CPU_FEROCEON default y help Say Y if you want to include kernel support for running user space @@ -601,7 +622,7 @@ config CPU_DCACHE_SIZE config CPU_DCACHE_WRITETHROUGH bool "Force write through D-cache" - depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE + depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FEROCEON) && !CPU_DCACHE_DISABLE default y if CPU_ARM925T help Say Y here to use the data cache in writethrough mode. Unless you diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 762702765fc3..44536a0b995a 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_CPU_SA110) += proc-sa110.o obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o +obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o obj-$(CONFIG_CPU_V6) += proc-v6.o obj-$(CONFIG_CPU_V7) += proc-v7.o diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S new file mode 100644 index 000000000000..fa0dc7e6f0ea --- /dev/null +++ b/arch/arm/mm/proc-feroceon.S @@ -0,0 +1,506 @@ +/* + * linux/arch/arm/mm/proc-feroceon.S: MMU functions for Feroceon + * + * Heavily based on proc-arm926.S + * Maintainer: Assaf Hoffman <hoffman@marvell.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/linkage.h> +#include <linux/init.h> +#include <asm/assembler.h> +#include <asm/elf.h> +#include <asm/pgtable-hwdef.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/ptrace.h> +#include "proc-macros.S" + +/* + * This is the maximum size of an area which will be invalidated + * using the single invalidate entry instructions. Anything larger + * than this, and we go for the whole cache. + * + * This value should be chosen such that we choose the cheapest + * alternative. + */ +#define CACHE_DLIMIT 16384 + +/* + * the cache line size of the I and D cache + */ +#define CACHE_DLINESIZE 32 + + .text +/* + * cpu_feroceon_proc_init() + */ +ENTRY(cpu_feroceon_proc_init) + mov pc, lr + +/* + * cpu_feroceon_proc_fin() + */ +ENTRY(cpu_feroceon_proc_fin) + stmfd sp!, {lr} + mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + msr cpsr_c, ip + bl feroceon_flush_kern_cache_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} + +/* + * cpu_feroceon_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_feroceon_reset) + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB +#ifdef CONFIG_MMU + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs +#endif + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + mov pc, r0 + +/* + * cpu_feroceon_do_idle() + * + * Called with IRQs disabled + */ + .align 10 +ENTRY(cpu_feroceon_do_idle) + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mov pc, lr + +/* + * flush_user_cache_all() + * + * Clean and invalidate all cache entries in a particular + * address space. + */ +ENTRY(feroceon_flush_user_cache_all) + /* FALLTHROUGH */ + +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(feroceon_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate + bne 1b +#endif + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcrne p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * flush_user_cache_range(start, end, flags) + * + * Clean and invalidate a range of cache entries in the + * specified address range. + * + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags describing address space + */ +ENTRY(feroceon_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bgt __flush_whole_cache +1: tst r2, #VM_EXEC +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE +#else + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE +#endif + cmp r0, r1 + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(feroceon_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(feroceon_coherent_user_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(feroceon_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) + */ +ENTRY(feroceon_dma_inv_range) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + tst r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry +#endif + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_clean_range(start, end) + * + * Clean the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) + */ +ENTRY(feroceon_dma_clean_range) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(feroceon_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry +#else + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(feroceon_cache_fns) + .long feroceon_flush_kern_cache_all + .long feroceon_flush_user_cache_all + .long feroceon_flush_user_cache_range + .long feroceon_coherent_kern_range + .long feroceon_coherent_user_range + .long feroceon_flush_kern_dcache_page + .long feroceon_dma_inv_range + .long feroceon_dma_clean_range + .long feroceon_dma_flush_range + +ENTRY(cpu_feroceon_dcache_clean_area) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* =============================== PageTable ============================== */ + +/* + * cpu_feroceon_switch_mm(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_feroceon_switch_mm) +#ifdef CONFIG_MMU + mov ip, #0 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else +@ && 'Clean & Invalidate whole DCache' +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate + bne 1b +#endif + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs +#endif + mov pc, lr + +/* + * cpu_feroceon_set_pte_ext(ptep, pte, ext) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_feroceon_set_pte_ext) +#ifdef CONFIG_MMU + str r1, [r0], #-2048 @ linux version + + eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY + + bic r2, r1, #PTE_SMALL_AP_MASK + bic r2, r2, #PTE_TYPE_MASK + orr r2, r2, #PTE_TYPE_SMALL + + tst r1, #L_PTE_USER @ User? + orrne r2, r2, #PTE_SMALL_AP_URO_SRW + + tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? + orreq r2, r2, #PTE_SMALL_AP_UNO_SRW + + tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? + movne r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r3, r2, #0x0a @ C & small page? + tst r3, #0x0b + biceq r2, r2, #4 +#endif + str r2, [r0] @ hardware version + mov r0, r0 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB +#endif + mov pc, lr + + __INIT + + .type __feroceon_setup, #function +__feroceon_setup: + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 +#ifdef CONFIG_MMU + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 +#endif + + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mov r0, #4 @ disable write-back on caches explicitly + mcr p15, 7, r0, c15, c0, 0 +#endif + + adr r5, feroceon_crval + ldmia r5, {r5, r6} + mrc p15, 0, r0, c1, c0 @ get control register v4 + bic r0, r0, r5 + orr r0, r0, r6 +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + orr r0, r0, #0x4000 @ .1.. .... .... .... +#endif + mov pc, lr + .size __feroceon_setup, . - __feroceon_setup + + /* + * R + * .RVI ZFRS BLDP WCAM + * .011 0001 ..11 0101 + * + */ + .type feroceon_crval, #object +feroceon_crval: + crval clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134 + + __INITDATA + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type feroceon_processor_functions, #object +feroceon_processor_functions: + .word v5t_early_abort + .word cpu_feroceon_proc_init + .word cpu_feroceon_proc_fin + .word cpu_feroceon_reset + .word cpu_feroceon_do_idle + .word cpu_feroceon_dcache_clean_area + .word cpu_feroceon_switch_mm + .word cpu_feroceon_set_pte_ext + .size feroceon_processor_functions, . - feroceon_processor_functions + + .section ".rodata" + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv5te" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v5" + .size cpu_elf_name, . - cpu_elf_name + + .type cpu_feroceon_name, #object +cpu_feroceon_name: + .asciz "Feroceon" + .size cpu_feroceon_name, . - cpu_feroceon_name + + .align + + .section ".proc.info.init", #alloc, #execinstr + +#ifdef CONFIG_CPU_FEROCEON_OLD_ID + .type __feroceon_old_id_proc_info,#object +__feroceon_old_id_proc_info: + .long 0x41069260 + .long 0xfffffff0 + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __feroceon_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_feroceon_name + .long feroceon_processor_functions + .long v4wbi_tlb_fns + .long v4wb_user_fns + .long feroceon_cache_fns + .size __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info +#endif + + .type __feroceon_proc_info,#object +__feroceon_proc_info: + .long 0x56055310 + .long 0xfffffff0 + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __feroceon_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_feroceon_name + .long feroceon_processor_functions + .long v4wbi_tlb_fns + .long v4wb_user_fns + .long feroceon_cache_fns + .size __feroceon_proc_info, . - __feroceon_proc_info |