diff options
Diffstat (limited to 'arch')
233 files changed, 8688 insertions, 5769 deletions
diff --git a/arch/arm/configs/da830_omapl137_defconfig b/arch/arm/configs/da830_omapl137_defconfig deleted file mode 100644 index 7c8e38f5c5ab..000000000000 --- a/arch/arm/configs/da830_omapl137_defconfig +++ /dev/null @@ -1,1254 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.30-rc2-davinci1 -# Wed May 13 15:33:29 2009 -# -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_HAVE_LATENCYTOP_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_GENERIC_HARDIRQS_NO__DO_IRQ=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 is not set -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set - -# -# RCU Subsystem -# -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set -# CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EMBEDDED=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -CONFIG_COMPAT_BRK=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_CLK=y -# CONFIG_SLOW_WORK is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" -# CONFIG_FREEZER is not set - -# -# 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_CLPS711X is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_GEMINI 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_KIRKWOOD is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_NS9XXX is not set -# CONFIG_ARCH_LOKI is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -CONFIG_ARCH_DAVINCI=y -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_W90X900 is not set -CONFIG_CP_INTC=y - -# -# TI DaVinci Implementations -# - -# -# DaVinci Core Type -# -# CONFIG_ARCH_DAVINCI_DM644x is not set -# CONFIG_ARCH_DAVINCI_DM646x is not set -# CONFIG_ARCH_DAVINCI_DM355 is not set -CONFIG_ARCH_DAVINCI_DA830=y - -# -# DaVinci Board Type -# -CONFIG_MACH_DAVINCI_DA830_EVM=y -CONFIG_DAVINCI_MUX=y -# CONFIG_DAVINCI_MUX_DEBUG is not set -# CONFIG_DAVINCI_MUX_WARNINGS is not set -CONFIG_DAVINCI_RESET_CLOCKS=y - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_ARM926T=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_PABRT_NOIFAR=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=y -# CONFIG_CPU_CACHE_ROUND_ROBIN is not set -# CONFIG_OUTER_CACHE is not set -CONFIG_COMMON_CLKDEV=y - -# -# Bus support -# -# CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -# 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_VMSPLIT_3G=y -# CONFIG_VMSPLIT_2G is not set -# CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PREEMPT=y -CONFIG_HZ=100 -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_ARCH_FLATMEM_HAS_HOLES=y -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -CONFIG_UNEVICTABLE_LRU=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_MLOCKED_PAGE_BIT=y -CONFIG_LEDS=y -# CONFIG_LEDS_CPU is not set -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 - -# -# CPU Power Management -# -# CONFIG_CPU_IDLE is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -# CONFIG_VFP is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_HAVE_AOUT=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options -# -# CONFIG_PM is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -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_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE 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=m -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=m -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETWORK_SECMARK is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_NETFILTER_ADVANCED=y - -# -# Core Netfilter Configuration -# -# CONFIG_NETFILTER_NETLINK_QUEUE is not set -# CONFIG_NETFILTER_NETLINK_LOG is not set -# CONFIG_NF_CONNTRACK is not set -# CONFIG_NETFILTER_XTABLES is not set -# CONFIG_IP_VS is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_NF_DEFRAG_IPV4 is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -# CONFIG_IP6_NF_IPTABLES 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_NET_DSA 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_PHONET is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -# CONFIG_WIRELESS is not set -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=1 -CONFIG_BLK_DEV_RAM_SIZE=32768 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -CONFIG_MISC_DEVICES=y -# CONFIG_ICS932S401 is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_ISL29003 is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=y -# CONFIG_EEPROM_LEGACY is not set -# CONFIG_EEPROM_93CX6 is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=m -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=m -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# 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_LIBFC is not set -# CONFIG_LIBFCOE is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -CONFIG_NETDEVICES=y -CONFIG_COMPAT_NET_DEV_OPS=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_VETH is not set -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -CONFIG_LXT_PHY=y -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -CONFIG_LSI_ET1011C_PHY=y -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_AX88796 is not set -# CONFIG_SMC91X is not set -CONFIG_TI_DAVINCI_EMAC=y -# CONFIG_DM9000 is not set -# CONFIG_ETHOC is not set -# CONFIG_SMC911X is not set -# CONFIG_SMSC911X is not set -# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set -# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set -# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set -# CONFIG_B44 is not set -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -CONFIG_NETCONSOLE=y -# CONFIG_NETCONSOLE_DYNAMIC is not set -CONFIG_NETPOLL=y -CONFIG_NETPOLL_TRAP=y -CONFIG_NET_POLL_CONTROLLER=y -# 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=m -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=m -CONFIG_INPUT_EVBUG=m - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=m -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -CONFIG_KEYBOARD_XTKBD=m -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_TOUCHSCREEN_AD7879_I2C is not set -# CONFIG_TOUCHSCREEN_AD7879 is not set -# CONFIG_TOUCHSCREEN_FUJITSU is not set -# CONFIG_TOUCHSCREEN_GUNZE is not set -# CONFIG_TOUCHSCREEN_ELO is not set -# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set -# CONFIG_TOUCHSCREEN_MTOUCH is not set -# CONFIG_TOUCHSCREEN_INEXIO is not set -# CONFIG_TOUCHSCREEN_MK712 is not set -# CONFIG_TOUCHSCREEN_PENMOUNT is not set -# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set -# CONFIG_TOUCHSCREEN_TOUCHWIN is not set -# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set -# CONFIG_TOUCHSCREEN_TSC2007 is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_DEVKMEM=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=m -# CONFIG_HW_RANDOM_TIMERIOMEM is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_HELPER_AUTO=y - -# -# I2C Hardware Bus support -# - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -CONFIG_I2C_DAVINCI=y -# CONFIG_I2C_GPIO is not set -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_SIMTEC is not set - -# -# External I2C/SMBus adapter drivers -# -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_TAOS_EVM is not set - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_PCA_PLATFORM is not set -# CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_DS1682 is not set -# CONFIG_SENSORS_PCA9539 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 -# CONFIG_SPI is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -# CONFIG_GPIO_SYSFS is not set - -# -# Memory mapped GPIO expanders: -# - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCA953X is not set -CONFIG_GPIO_PCF857X=m - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -# CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_DAVINCI_WATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_TPS65010 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_PCF50633 is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# CONFIG_DAB is not set - -# -# Graphics support -# -# 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 -CONFIG_SOUND=m -# CONFIG_SOUND_OSS_CORE is not set -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_JACK=y -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_HRTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set -CONFIG_SND_ARM=y -CONFIG_SND_SOC=m -CONFIG_SND_DAVINCI_SOC=m -CONFIG_SND_SOC_I2C_AND_SPI=m -# CONFIG_SND_SOC_ALL_CODECS is not set -# CONFIG_SOUND_PRIME is not set -# CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_USB_MUSB_HOST is not set -# CONFIG_USB_MUSB_PERIPHERAL is not set -# CONFIG_USB_MUSB_OTG is not set -# CONFIG_USB_GADGET_MUSB_HDRC is not set -# CONFIG_USB_GADGET_AT91 is not set -# CONFIG_USB_GADGET_ATMEL_USBA is not set -# CONFIG_USB_GADGET_FSL_USB2 is not set -# CONFIG_USB_GADGET_LH7A40X is not set -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_PXA25X is not set -# CONFIG_USB_GADGET_PXA27X is not set -# CONFIG_USB_GADGET_S3C2410 is not set -# CONFIG_USB_GADGET_IMX is not set -# CONFIG_USB_GADGET_M66592 is not set -# CONFIG_USB_GADGET_AMD5536UDC is not set -# CONFIG_USB_GADGET_FSL_QE is not set -# CONFIG_USB_GADGET_CI13XXX is not set -# CONFIG_USB_GADGET_NET2280 is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_ZERO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_ACCESSIBILITY is not set -# CONFIG_NEW_LEDS is not set -CONFIG_RTC_LIB=y -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_REGULATOR is not set -# CONFIG_UIO is not set -# CONFIG_STAGING is not set - -# -# 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_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4_FS is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y -CONFIG_XFS_FS=m -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_DEBUG is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set -CONFIG_DNOTIFY=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -# CONFIG_FUSE_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_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_PROC_PAGE_MONITOR=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 -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y -# CONFIG_SQUASHFS is not set -# CONFIG_VXFS_FS is not set -CONFIG_MINIX_FS=m -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -# CONFIG_NILFS2_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_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V3_ACL is not set -# CONFIG_NFSD_V4 is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT 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 is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# 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 is not set -# 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=m -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# 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=m -# CONFIG_DLM is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -CONFIG_DETECT_HUNG_TASK=y -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -CONFIG_SCHED_DEBUG=y -# CONFIG_SCHEDSTATS is not set -CONFIG_TIMER_STATS=y -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_SLUB_DEBUG_ON is not set -# CONFIG_SLUB_STATS is not set -CONFIG_DEBUG_PREEMPT=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_PI_LIST=y -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_DEBUG_MUTEXES=y -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_LATENCYTOP is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -# CONFIG_PAGE_POISONING is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_TRACING_SUPPORT=y - -# -# Tracers -# -# CONFIG_FUNCTION_TRACER is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_PREEMPT_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_EVENT_TRACER is not set -# CONFIG_BOOT_TRACER is not set -# CONFIG_TRACE_BRANCH_PROFILING is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_KMEMTRACE is not set -# CONFIG_WORKQUEUE_TRACER is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -CONFIG_ARM_UNWIND=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_LL is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -# CONFIG_CRYPTO_FIPS is not set -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MANAGER2 is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set - -# -# Random Number Generation -# -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_HW is not set -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_CRC_CCITT=m -# CONFIG_CRC16 is not set -CONFIG_CRC_T10DIF=m -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_NLATTR=y diff --git a/arch/arm/configs/da850_omapl138_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 842a70b079bf..50bd25a10f0d 100644 --- a/arch/arm/configs/da850_omapl138_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -1,15 +1,13 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.30-davinci1 -# Mon Jun 29 07:54:15 2009 +# Linux kernel version: 2.6.32-rc5 +# Thu Oct 22 12:19:19 2009 # 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_HAVE_LATENCYTOP_SUPPORT=y @@ -18,14 +16,14 @@ 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_ARCH_HAS_CPUFREQ=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ZONE_DMA=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y # # General setup @@ -48,11 +46,12 @@ CONFIG_POSIX_MQUEUE_SYSCTL=y # # RCU Subsystem # -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -62,8 +61,7 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y @@ -80,7 +78,6 @@ CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y @@ -93,6 +90,10 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y @@ -100,12 +101,16 @@ CONFIG_COMPAT_BRK=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -118,7 +123,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y -# CONFIG_LBD is not set +CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -139,19 +144,22 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # System Type # +CONFIG_MMU=y # 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_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -160,25 +168,27 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_NS9XXX is not set # CONFIG_ARCH_LOKI is not set # CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_MXC is not set # CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_MSM is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set CONFIG_ARCH_DAVINCI=y # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_BCMRING is not set CONFIG_CP_INTC=y # @@ -191,7 +201,7 @@ CONFIG_CP_INTC=y # CONFIG_ARCH_DAVINCI_DM644x is not set # CONFIG_ARCH_DAVINCI_DM355 is not set # CONFIG_ARCH_DAVINCI_DM646x is not set -# CONFIG_ARCH_DAVINCI_DA830 is not set +CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y CONFIG_ARCH_DAVINCI_DA8XX=y # CONFIG_ARCH_DAVINCI_DM365 is not set @@ -199,7 +209,14 @@ CONFIG_ARCH_DAVINCI_DA8XX=y # # DaVinci Board Type # +CONFIG_MACH_DAVINCI_DA830_EVM=y +CONFIG_DA830_UI=y +CONFIG_DA830_UI_LCD=y +# CONFIG_DA830_UI_NAND is not set CONFIG_MACH_DAVINCI_DA850_EVM=y +CONFIG_DA850_UI_EXP=y +CONFIG_DA850_UI_NONE=y +# CONFIG_DA850_UI_RMII is not set CONFIG_DAVINCI_MUX=y # CONFIG_DAVINCI_MUX_DEBUG is not set # CONFIG_DAVINCI_MUX_WARNINGS is not set @@ -212,7 +229,7 @@ CONFIG_CPU_32=y CONFIG_CPU_ARM926T=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_PABRT_LEGACY=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y @@ -225,9 +242,9 @@ CONFIG_CPU_CP15_MMU=y 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_CPU_DCACHE_WRITETHROUGH=y # CONFIG_CPU_CACHE_ROUND_ROBIN is not set -# CONFIG_OUTER_CACHE is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 CONFIG_COMMON_CLKDEV=y # @@ -248,11 +265,12 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set -# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set # CONFIG_HIGHMEM is not set @@ -268,12 +286,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y -CONFIG_UNEVICTABLE_LRU=y CONFIG_HAVE_MLOCK=y CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_LEDS=y # CONFIG_LEDS_CPU is not set CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set # # Boot options @@ -287,7 +307,24 @@ CONFIG_CMDLINE="" # # CPU Power Management # -# CONFIG_CPU_IDLE is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=m +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y # # Floating point emulation @@ -401,6 +438,7 @@ CONFIG_NETFILTER_ADVANCED=y # CONFIG_IP6_NF_IPTABLES is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -415,6 +453,7 @@ CONFIG_NETFILTER_ADVANCED=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set @@ -440,6 +479,7 @@ CONFIG_NETFILTER_ADVANCED=y # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -460,6 +500,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768 # CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set CONFIG_MISC_DEVICES=y # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -471,6 +512,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_AT24=y # CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -494,10 +536,6 @@ CONFIG_BLK_DEV_SD=m # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -522,7 +560,6 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y -CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -553,7 +590,7 @@ CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_AX88796 is not set # CONFIG_SMC91X is not set -# CONFIG_TI_DAVINCI_EMAC is not set +CONFIG_TI_DAVINCI_EMAC=y # CONFIG_DM9000 is not set # CONFIG_ETHOC is not set # CONFIG_SMC911X is not set @@ -567,12 +604,11 @@ CONFIG_MII=y # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set - -# -# Wireless LAN -# +CONFIG_WLAN=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set @@ -588,6 +624,7 @@ CONFIG_NETPOLL=y CONFIG_NETPOLL_TRAP=y CONFIG_NET_POLL_CONTROLLER=y # CONFIG_ISDN is not set +# CONFIG_PHONE is not set # # Input device support @@ -611,23 +648,30 @@ CONFIG_INPUT_EVBUG=m # Input Device Drivers # CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set CONFIG_KEYBOARD_ATKBD=m -# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_QT2160 is not set # CONFIG_KEYBOARD_LKKBD is not set -CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set # CONFIG_KEYBOARD_STOWAWAY is not set -CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_SUNKBD is not set +CONFIG_KEYBOARD_XTKBD=m # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_AD7879_I2C is not set # CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_EETI is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_MK712 is not set @@ -636,6 +680,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_TOUCHWIN is not set # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set # CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set # CONFIG_INPUT_MISC is not set # @@ -684,6 +729,7 @@ CONFIG_HW_RANDOM=m # CONFIG_TCG_TPM is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_HELPER_AUTO=y @@ -695,6 +741,7 @@ CONFIG_I2C_HELPER_AUTO=y # I2C system bus drivers (mostly embedded / system-on-chip) # CONFIG_I2C_DAVINCI=y +# CONFIG_I2C_DESIGNWARE is not set # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SIMTEC is not set @@ -715,14 +762,17 @@ CONFIG_I2C_DAVINCI=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_SENSORS_PCA9539 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 # CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set @@ -736,8 +786,8 @@ CONFIG_GPIOLIB=y # I2C GPIO expanders: # # CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCA953X is not set -CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCF857X=y # # PCI GPIO expanders: @@ -746,11 +796,14 @@ CONFIG_GPIO_PCF857X=m # # SPI GPIO expanders: # + +# +# AC97 GPIO expanders: +# # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set @@ -782,31 +835,56 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TC6393XB is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_PCF50633 is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# CONFIG_DAB is not set +# CONFIG_AB3100_CORE is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_TPS65023 is not set +CONFIG_REGULATOR_TPS6507X=y +# CONFIG_MEDIA_SUPPORT is not set # # Graphics support # # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_DAVINCI is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FB_DA8XX=y +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -819,6 +897,16 @@ CONFIG_SSB_POSSIBLE=y # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=m # CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=m @@ -834,6 +922,11 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_MTPAV is not set @@ -842,6 +935,8 @@ CONFIG_SND_DRIVERS=y CONFIG_SND_ARM=y CONFIG_SND_SOC=m CONFIG_SND_DAVINCI_SOC=m +# CONFIG_SND_DA830_SOC_EVM is not set +# CONFIG_SND_DA850_SOC_EVM is not set CONFIG_SND_SOC_I2C_AND_SPI=m # CONFIG_SND_SOC_ALL_CODECS is not set # CONFIG_SOUND_PRIME is not set @@ -849,14 +944,17 @@ CONFIG_SND_SOC_I2C_AND_SPI=m # CONFIG_USB_SUPPORT is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set -# CONFIG_ACCESSIBILITY is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set -# CONFIG_REGULATOR is not set # CONFIG_UIO is not set + +# +# TI VLYNQ +# # CONFIG_STAGING is not set # @@ -877,14 +975,17 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y CONFIG_XFS_FS=m # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set # CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -943,7 +1044,6 @@ CONFIG_MINIX_FS=m # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1039,6 +1139,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -1056,6 +1157,7 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_PI_LIST=y @@ -1076,29 +1178,29 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_TRACING_SUPPORT=y - -# -# Tracers -# +CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_EVENT_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set # CONFIG_BOOT_TRACER is not set -# CONFIG_TRACE_BRANCH_PROFILING is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1125,7 +1227,6 @@ CONFIG_CRYPTO=y # # Crypto core or helper # -# CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set # CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set @@ -1157,11 +1258,13 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set # # Digest # # CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index ddffe39d9f87..bd656e8e6e4c 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -1,14 +1,13 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.31-rc3-davinci1 -# Fri Jul 17 08:26:52 2009 +# Linux kernel version: 2.6.32-rc4 +# Mon Oct 12 14:13:12 2009 # 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_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -46,11 +45,12 @@ CONFIG_POSIX_MQUEUE_SYSCTL=y # # RCU Subsystem # -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -91,17 +91,15 @@ CONFIG_SHMEM=y CONFIG_AIO=y # -# Performance Counters +# Kernel Performance Events And Counters # CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLUB_DEBUG=y -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_KPROBES=y @@ -145,6 +143,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # System Type # +CONFIG_MMU=y # CONFIG_ARCH_AAEC2000 is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set @@ -159,6 +158,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -181,11 +181,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_U300 is not set CONFIG_ARCH_DAVINCI=y # CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set CONFIG_AINTC=y CONFIG_ARCH_DAVINCI_DMx=y @@ -208,6 +210,7 @@ CONFIG_ARCH_DAVINCI_DM365=y # CONFIG_MACH_DAVINCI_EVM=y CONFIG_MACH_SFFSDR=y +CONFIG_MACH_NEUROS_OSD2=y CONFIG_MACH_DAVINCI_DM355_EVM=y CONFIG_MACH_DM355_LEOPARD=y CONFIG_MACH_DAVINCI_DM6467_EVM=y @@ -224,7 +227,7 @@ CONFIG_CPU_32=y CONFIG_CPU_ARM926T=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_PABRT_LEGACY=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y @@ -239,6 +242,7 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set # CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 CONFIG_COMMON_CLKDEV=y # @@ -259,6 +263,8 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y @@ -280,6 +286,7 @@ CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_HAVE_MLOCK=y CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_LEDS=y # CONFIG_LEDS_CPU is not set @@ -412,6 +419,7 @@ CONFIG_NETFILTER_ADVANCED=y # CONFIG_IP6_NF_IPTABLES is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -452,6 +460,7 @@ CONFIG_NETFILTER_ADVANCED=y # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -461,9 +470,9 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_CONNECTOR is not set CONFIG_MTD=m # CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set # CONFIG_MTD_AR7_PARTS is not set @@ -499,7 +508,7 @@ CONFIG_MTD_CFI_I1=y CONFIG_MTD_CFI_I2=y # CONFIG_MTD_CFI_I4 is not set # CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_INTELEXT=m CONFIG_MTD_CFI_AMDSTD=m # CONFIG_MTD_CFI_STAA is not set CONFIG_MTD_CFI_UTIL=m @@ -694,12 +703,10 @@ CONFIG_DM9000_DEBUGLEVEL=4 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_B44 is not set # CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set - -# -# Wireless LAN -# +CONFIG_WLAN=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set @@ -734,6 +741,7 @@ CONFIG_NETPOLL=y CONFIG_NETPOLL_TRAP=y CONFIG_NET_POLL_CONTROLLER=y # CONFIG_ISDN is not set +# CONFIG_PHONE is not set # # Input device support @@ -745,10 +753,7 @@ CONFIG_INPUT=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=m CONFIG_INPUT_EVBUG=m @@ -757,12 +762,16 @@ CONFIG_INPUT_EVBUG=m # Input Device Drivers # CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set CONFIG_KEYBOARD_ATKBD=m +# CONFIG_QT2160 is not set # CONFIG_KEYBOARD_LKKBD is not set CONFIG_KEYBOARD_GPIO=y # CONFIG_KEYBOARD_MATRIX is not set # CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set CONFIG_KEYBOARD_XTKBD=m @@ -777,6 +786,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_MK712 is not set @@ -787,7 +797,17 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set # CONFIG_TOUCHSCREEN_TSC2007 is not set # CONFIG_TOUCHSCREEN_W90X900 is not set -# CONFIG_INPUT_MISC is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +CONFIG_INPUT_DM355EVM=m +CONFIG_INPUT_DM365EVM=m # # Hardware I/O ports @@ -828,13 +848,13 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=m -# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_HELPER_AUTO=y @@ -868,13 +888,17 @@ CONFIG_I2C_DAVINCI=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_SENSORS_PCA9539 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 # CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set @@ -889,7 +913,7 @@ CONFIG_GPIOLIB=y # # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set -CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_PCF857X=y # # PCI GPIO expanders: @@ -898,10 +922,19 @@ CONFIG_GPIO_PCF857X=m # # SPI GPIO expanders: # + +# +# AC97 GPIO expanders: +# # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# # CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set # CONFIG_SENSORS_ADM1021 is not set @@ -950,6 +983,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set # CONFIG_SENSORS_VT1211 is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83791D is not set @@ -959,9 +993,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set # CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set @@ -988,7 +1020,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_ASIC3 is not set -# CONFIG_MFD_DM355EVM_MSP is not set +CONFIG_MFD_DM355EVM_MSP=y # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_TPS65010 is not set @@ -999,9 +1031,11 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TC6393XB is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set +# CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set # @@ -1013,9 +1047,9 @@ CONFIG_FB=y CONFIG_FIRMWARE_EDID=y # CONFIG_FB_DDC is not set # CONFIG_FB_BOOT_VESA_SUPPORT is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set @@ -1032,6 +1066,7 @@ CONFIG_FIRMWARE_EDID=y # Frame buffer hardware drivers # # CONFIG_FB_S1D13XXX is not set +CONFIG_FB_DAVINCI=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1101,7 +1136,6 @@ CONFIG_SND_SOC_TLV320AIC3X=m # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m -# CONFIG_HID_DEBUG is not set # CONFIG_HIDRAW is not set # @@ -1130,6 +1164,7 @@ CONFIG_HID_CYPRESS=m CONFIG_HID_EZKEY=m # CONFIG_HID_KYE is not set CONFIG_HID_GYRATION=m +# CONFIG_HID_TWINHAN is not set # CONFIG_HID_KENSINGTON is not set CONFIG_HID_LOGITECH=m # CONFIG_LOGITECH_FF is not set @@ -1176,6 +1211,7 @@ CONFIG_USB_MON=m # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HWA_HCD is not set @@ -1269,6 +1305,7 @@ CONFIG_USB_GADGET_SELECTED=y # CONFIG_USB_GADGET_LH7A40X is not set # CONFIG_USB_GADGET_OMAP is not set # CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_R8A66597 is not set # CONFIG_USB_GADGET_PXA27X is not set # CONFIG_USB_GADGET_S3C_HSOTG is not set # CONFIG_USB_GADGET_IMX is not set @@ -1286,6 +1323,7 @@ CONFIG_USB_ZERO=m # CONFIG_USB_AUDIO is not set CONFIG_USB_ETH=m CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set CONFIG_USB_GADGETFS=m CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_FILE_STORAGE_TEST is not set @@ -1316,8 +1354,10 @@ CONFIG_MMC_BLOCK=m # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +CONFIG_MMC_DAVINCI=m # CONFIG_MEMSTICK is not set -# CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=m @@ -1345,6 +1385,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=m @@ -1370,6 +1411,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_DM355EVM is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set @@ -1399,8 +1441,11 @@ CONFIG_RTC_INTF_DEV=y # # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set -# CONFIG_REGULATOR is not set # CONFIG_UIO is not set + +# +# TI VLYNQ +# # CONFIG_STAGING is not set # @@ -1429,6 +1474,7 @@ CONFIG_XFS_FS=m # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -1500,7 +1546,6 @@ CONFIG_MINIX_FS=m # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1596,6 +1641,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -1634,11 +1680,14 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set @@ -1663,7 +1712,7 @@ CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -CONFIG_ARM_UNWIND=y +# CONFIG_ARM_UNWIND is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set @@ -1681,7 +1730,6 @@ CONFIG_CRYPTO=y # # Crypto core or helper # -# CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set # CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set @@ -1713,11 +1761,13 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set # # Digest # # CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 40866c643f13..033bfede6b67 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -32,11 +32,13 @@ config ARCH_DAVINCI_DA830 bool "DA830/OMAP-L137 based system" select CP_INTC select ARCH_DAVINCI_DA8XX + select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1 config ARCH_DAVINCI_DA850 bool "DA850/OMAP-L138 based system" select CP_INTC select ARCH_DAVINCI_DA8XX + select ARCH_HAS_CPUFREQ config ARCH_DAVINCI_DA8XX bool @@ -63,6 +65,13 @@ config MACH_SFFSDR Say Y here to select the Lyrtech Small Form Factor Software Defined Radio (SFFSDR) board. +config MACH_NEUROS_OSD2 + bool "Neuros OSD2 Open Television Set Top Box" + depends on ARCH_DAVINCI_DM644x + help + Configure this option to specify the whether the board used + for development is a Neuros OSD2 Open Set Top Box. + config MACH_DAVINCI_DM355_EVM bool "TI DM355 EVM" default ARCH_DAVINCI_DM355 @@ -98,16 +107,66 @@ config MACH_DAVINCI_DA830_EVM bool "TI DA830/OMAP-L137 Reference Platform" default ARCH_DAVINCI_DA830 depends on ARCH_DAVINCI_DA830 + select GPIO_PCF857X help Say Y here to select the TI DA830/OMAP-L137 Evaluation Module. +choice + prompt "Select DA830/OMAP-L137 UI board peripheral" + depends on MACH_DAVINCI_DA830_EVM + help + The presence of UI card on the DA830/OMAP-L137 EVM is detected + automatically based on successful probe of the I2C based GPIO + expander on that board. This option selected in this menu has + an effect only in case of a successful UI card detection. + +config DA830_UI_LCD + bool "LCD" + help + Say Y here to use the LCD as a framebuffer or simple character + display. + +config DA830_UI_NAND + bool "NAND flash" + help + Say Y here to use the NAND flash. Do not forget to setup + the switch correctly. +endchoice + config MACH_DAVINCI_DA850_EVM bool "TI DA850/OMAP-L138 Reference Platform" default ARCH_DAVINCI_DA850 depends on ARCH_DAVINCI_DA850 + select GPIO_PCA953X help Say Y here to select the TI DA850/OMAP-L138 Evaluation Module. +choice + prompt "Select peripherals connected to expander on UI board" + depends on MACH_DAVINCI_DA850_EVM + help + The presence of User Interface (UI) card on the DA850/OMAP-L138 + EVM is detected automatically based on successful probe of the I2C + based GPIO expander on that card. This option selected in this + menu has an effect only in case of a successful UI card detection. + +config DA850_UI_NONE + bool "No peripheral is enabled" + help + Say Y if you do not want to enable any of the peripherals connected + to TCA6416 expander on DA850/OMAP-L138 EVM UI card + +config DA850_UI_RMII + bool "RMII Ethernet PHY" + help + Say Y if you want to use the RMII PHY on the DA850/OMAP-L138 EVM. + This PHY is found on the UI daughter card that is supplied with + the EVM. + NOTE: Please take care while choosing this option, MII PHY will + not be functional if RMII mode is selected. + +endchoice + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 2e11e847313b..eeb9230d8844 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -23,9 +23,14 @@ obj-$(CONFIG_CP_INTC) += cp_intc.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-dm644x-evm.o obj-$(CONFIG_MACH_SFFSDR) += board-sffsdr.o +obj-$(CONFIG_MACH_NEUROS_OSD2) += board-neuros-osd2.o obj-$(CONFIG_MACH_DAVINCI_DM355_EVM) += board-dm355-evm.o obj-$(CONFIG_MACH_DM355_LEOPARD) += board-dm355-leopard.o obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM) += board-dm646x-evm.o obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o + +# Power Management +obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index bfbb63936f33..31dc9901e556 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -10,51 +10,194 @@ * or implied. */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> #include <linux/console.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> #include <linux/i2c.h> +#include <linux/i2c/pcf857x.h> #include <linux/i2c/at24.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <mach/common.h> -#include <mach/irqs.h> #include <mach/cp_intc.h> +#include <mach/mux.h> +#include <mach/nand.h> #include <mach/da8xx.h> -#include <mach/asp.h> +#include <mach/usb.h> #define DA830_EVM_PHY_MASK 0x0 #define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ -static struct at24_platform_data da830_evm_i2c_eeprom_info = { - .byte_len = SZ_256K / 8, - .page_size = 64, - .flags = AT24_FLAG_ADDR16, - .setup = davinci_get_mac_addr, - .context = (void *)0x7f00, -}; +#define DA830_EMIF25_ASYNC_DATA_CE3_BASE 0x62000000 +#define DA830_EMIF25_CONTROL_BASE 0x68000000 -static struct i2c_board_info __initdata da830_evm_i2c_devices[] = { - { - I2C_BOARD_INFO("24c256", 0x50), - .platform_data = &da830_evm_i2c_eeprom_info, - }, - { - I2C_BOARD_INFO("tlv320aic3x", 0x18), - } +/* + * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. + */ +#define ON_BD_USB_DRV GPIO_TO_PIN(1, 15) +#define ON_BD_USB_OVC GPIO_TO_PIN(2, 4) + +static const short da830_evm_usb11_pins[] = { + DA830_GPIO1_15, DA830_GPIO2_4, + -1 }; -static struct davinci_i2c_platform_data da830_evm_i2c_0_pdata = { - .bus_freq = 100, /* kHz */ - .bus_delay = 0, /* usec */ +static da8xx_ocic_handler_t da830_evm_usb_ocic_handler; + +static int da830_evm_usb_set_power(unsigned port, int on) +{ + gpio_set_value(ON_BD_USB_DRV, on); + return 0; +} + +static int da830_evm_usb_get_power(unsigned port) +{ + return gpio_get_value(ON_BD_USB_DRV); +} + +static int da830_evm_usb_get_oci(unsigned port) +{ + return !gpio_get_value(ON_BD_USB_OVC); +} + +static irqreturn_t da830_evm_usb_ocic_irq(int, void *); + +static int da830_evm_usb_ocic_notify(da8xx_ocic_handler_t handler) +{ + int irq = gpio_to_irq(ON_BD_USB_OVC); + int error = 0; + + if (handler != NULL) { + da830_evm_usb_ocic_handler = handler; + + error = request_irq(irq, da830_evm_usb_ocic_irq, IRQF_DISABLED | + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "OHCI over-current indicator", NULL); + if (error) + printk(KERN_ERR "%s: could not request IRQ to watch " + "over-current indicator changes\n", __func__); + } else + free_irq(irq, NULL); + + return error; +} + +static struct da8xx_ohci_root_hub da830_evm_usb11_pdata = { + .set_power = da830_evm_usb_set_power, + .get_power = da830_evm_usb_get_power, + .get_oci = da830_evm_usb_get_oci, + .ocic_notify = da830_evm_usb_ocic_notify, + + /* TPS2065 switch @ 5V */ + .potpgt = (3 + 1) / 2, /* 3 ms max */ }; +static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id) +{ + da830_evm_usb_ocic_handler(&da830_evm_usb11_pdata, 1); + return IRQ_HANDLED; +} + +static __init void da830_evm_usb_init(void) +{ + u32 cfgchip2; + int ret; + + /* + * Set up USB clock/mode in the CFGCHIP2 register. + * FYI: CFGCHIP2 is 0x0000ef00 initially. + */ + cfgchip2 = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG)); + + /* USB2.0 PHY reference clock is 24 MHz */ + cfgchip2 &= ~CFGCHIP2_REFFREQ; + cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ; + + /* + * Select internal reference clock for USB 2.0 PHY + * and use it as a clock source for USB 1.1 PHY + * (this is the default setting anyway). + */ + cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX; + cfgchip2 |= CFGCHIP2_USB2PHYCLKMUX; + + /* + * We have to override VBUS/ID signals when MUSB is configured into the + * host-only mode -- ID pin will float if no cable is connected, so the + * controller won't be able to drive VBUS thinking that it's a B-device. + * Otherwise, we want to use the OTG mode and enable VBUS comparators. + */ + cfgchip2 &= ~CFGCHIP2_OTGMODE; +#ifdef CONFIG_USB_MUSB_HOST + cfgchip2 |= CFGCHIP2_FORCE_HOST; +#else + cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN; +#endif + + __raw_writel(cfgchip2, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG)); + + /* USB_REFCLKIN is not used. */ + ret = davinci_cfg_reg(DA830_USB0_DRVVBUS); + if (ret) + pr_warning("%s: USB 2.0 PinMux setup failed: %d\n", + __func__, ret); + else { + /* + * TPS2065 switch @ 5V supplies 1 A (sustains 1.5 A), + * with the power on to power good time of 3 ms. + */ + ret = da8xx_register_usb20(1000, 3); + if (ret) + pr_warning("%s: USB 2.0 registration failed: %d\n", + __func__, ret); + } + + ret = da8xx_pinmux_setup(da830_evm_usb11_pins); + if (ret) { + pr_warning("%s: USB 1.1 PinMux setup failed: %d\n", + __func__, ret); + return; + } + + ret = gpio_request(ON_BD_USB_DRV, "ON_BD_USB_DRV"); + if (ret) { + printk(KERN_ERR "%s: failed to request GPIO for USB 1.1 port " + "power control: %d\n", __func__, ret); + return; + } + gpio_direction_output(ON_BD_USB_DRV, 0); + + ret = gpio_request(ON_BD_USB_OVC, "ON_BD_USB_OVC"); + if (ret) { + printk(KERN_ERR "%s: failed to request GPIO for USB 1.1 port " + "over-current indicator: %d\n", __func__, ret); + return; + } + gpio_direction_input(ON_BD_USB_OVC); + + ret = da8xx_register_usb11(&da830_evm_usb11_pdata); + if (ret) + pr_warning("%s: USB 1.1 registration failed: %d\n", + __func__, ret); +} + static struct davinci_uart_config da830_evm_uart_config __initdata = { .enabled_uarts = 0x7, }; +static const short da830_evm_mcasp1_pins[] = { + DA830_AHCLKX1, DA830_ACLKX1, DA830_AFSX1, DA830_AHCLKR1, DA830_AFSR1, + DA830_AMUTE1, DA830_AXR1_0, DA830_AXR1_1, DA830_AXR1_2, DA830_AXR1_5, + DA830_ACLKR1, DA830_AXR1_6, DA830_AXR1_7, DA830_AXR1_8, DA830_AXR1_10, + DA830_AXR1_11, + -1 +}; + static u8 da830_iis_serializer_direction[] = { RX_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, TX_MODE, INACTIVE_MODE, INACTIVE_MODE, @@ -74,6 +217,271 @@ static struct snd_platform_data da830_evm_snd_data = { .rxnumevt = 1, }; +/* + * GPIO2[1] is used as MMC_SD_WP and GPIO2[2] as MMC_SD_INS. + */ +static const short da830_evm_mmc_sd_pins[] = { + DA830_MMCSD_DAT_0, DA830_MMCSD_DAT_1, DA830_MMCSD_DAT_2, + DA830_MMCSD_DAT_3, DA830_MMCSD_DAT_4, DA830_MMCSD_DAT_5, + DA830_MMCSD_DAT_6, DA830_MMCSD_DAT_7, DA830_MMCSD_CLK, + DA830_MMCSD_CMD, DA830_GPIO2_1, DA830_GPIO2_2, + -1 +}; + +#define DA830_MMCSD_WP_PIN GPIO_TO_PIN(2, 1) + +static int da830_evm_mmc_get_ro(int index) +{ + return gpio_get_value(DA830_MMCSD_WP_PIN); +} + +static struct davinci_mmc_config da830_evm_mmc_config = { + .get_ro = da830_evm_mmc_get_ro, + .wires = 4, + .max_freq = 50000000, + .caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, + .version = MMC_CTLR_VERSION_2, +}; + +static inline void da830_evm_init_mmc(void) +{ + int ret; + + ret = da8xx_pinmux_setup(da830_evm_mmc_sd_pins); + if (ret) { + pr_warning("da830_evm_init: mmc/sd mux setup failed: %d\n", + ret); + return; + } + + ret = gpio_request(DA830_MMCSD_WP_PIN, "MMC WP"); + if (ret) { + pr_warning("da830_evm_init: can not open GPIO %d\n", + DA830_MMCSD_WP_PIN); + return; + } + gpio_direction_input(DA830_MMCSD_WP_PIN); + + ret = da8xx_register_mmcsd0(&da830_evm_mmc_config); + if (ret) { + pr_warning("da830_evm_init: mmc/sd registration failed: %d\n", + ret); + gpio_free(DA830_MMCSD_WP_PIN); + } +} + +/* + * UI board NAND/NOR flashes only use 8-bit data bus. + */ +static const short da830_evm_emif25_pins[] = { + DA830_EMA_D_0, DA830_EMA_D_1, DA830_EMA_D_2, DA830_EMA_D_3, + DA830_EMA_D_4, DA830_EMA_D_5, DA830_EMA_D_6, DA830_EMA_D_7, + DA830_EMA_A_0, DA830_EMA_A_1, DA830_EMA_A_2, DA830_EMA_A_3, + DA830_EMA_A_4, DA830_EMA_A_5, DA830_EMA_A_6, DA830_EMA_A_7, + DA830_EMA_A_8, DA830_EMA_A_9, DA830_EMA_A_10, DA830_EMA_A_11, + DA830_EMA_A_12, DA830_EMA_BA_0, DA830_EMA_BA_1, DA830_NEMA_WE, + DA830_NEMA_CS_2, DA830_NEMA_CS_3, DA830_NEMA_OE, DA830_EMA_WAIT_0, + -1 +}; + +#if defined(CONFIG_MMC_DAVINCI) || defined(CONFIG_MMC_DAVINCI_MODULE) +#define HAS_MMC 1 +#else +#define HAS_MMC 0 +#endif + +#ifdef CONFIG_DA830_UI_NAND +static struct mtd_partition da830_evm_nand_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + [0] = { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + [1] = { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* kernel */ + [2] = { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0, + }, + /* file system */ + [3] = { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0, + } +}; + +/* flash bbt decriptors */ +static uint8_t da830_evm_nand_bbt_pattern[] = { 'B', 'b', 't', '0' }; +static uint8_t da830_evm_nand_mirror_pattern[] = { '1', 't', 'b', 'B' }; + +static struct nand_bbt_descr da830_evm_nand_bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | + NAND_BBT_WRITE | NAND_BBT_2BIT | + NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 2, + .len = 4, + .veroffs = 16, + .maxblocks = 4, + .pattern = da830_evm_nand_bbt_pattern +}; + +static struct nand_bbt_descr da830_evm_nand_bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | + NAND_BBT_WRITE | NAND_BBT_2BIT | + NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 2, + .len = 4, + .veroffs = 16, + .maxblocks = 4, + .pattern = da830_evm_nand_mirror_pattern +}; + +static struct davinci_nand_pdata da830_evm_nand_pdata = { + .parts = da830_evm_nand_partitions, + .nr_parts = ARRAY_SIZE(da830_evm_nand_partitions), + .ecc_mode = NAND_ECC_HW, + .ecc_bits = 4, + .options = NAND_USE_FLASH_BBT, + .bbt_td = &da830_evm_nand_bbt_main_descr, + .bbt_md = &da830_evm_nand_bbt_mirror_descr, +}; + +static struct resource da830_evm_nand_resources[] = { + [0] = { /* First memory resource is NAND I/O window */ + .start = DA830_EMIF25_ASYNC_DATA_CE3_BASE, + .end = DA830_EMIF25_ASYNC_DATA_CE3_BASE + PAGE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { /* Second memory resource is AEMIF control registers */ + .start = DA830_EMIF25_CONTROL_BASE, + .end = DA830_EMIF25_CONTROL_BASE + SZ_32K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da830_evm_nand_device = { + .name = "davinci_nand", + .id = 1, + .dev = { + .platform_data = &da830_evm_nand_pdata, + }, + .num_resources = ARRAY_SIZE(da830_evm_nand_resources), + .resource = da830_evm_nand_resources, +}; + +static inline void da830_evm_init_nand(int mux_mode) +{ + int ret; + + if (HAS_MMC) { + pr_warning("WARNING: both MMC/SD and NAND are " + "enabled, but they share AEMIF pins.\n" + "\tDisable MMC/SD for NAND support.\n"); + return; + } + + ret = da8xx_pinmux_setup(da830_evm_emif25_pins); + if (ret) + pr_warning("da830_evm_init: emif25 mux setup failed: %d\n", + ret); + + ret = platform_device_register(&da830_evm_nand_device); + if (ret) + pr_warning("da830_evm_init: NAND device not registered.\n"); + + gpio_direction_output(mux_mode, 1); +} +#else +static inline void da830_evm_init_nand(int mux_mode) { } +#endif + +#ifdef CONFIG_DA830_UI_LCD +static inline void da830_evm_init_lcdc(int mux_mode) +{ + int ret; + + ret = da8xx_pinmux_setup(da830_lcdcntl_pins); + if (ret) + pr_warning("da830_evm_init: lcdcntl mux setup failed: %d\n", + ret); + + ret = da8xx_register_lcdc(&sharp_lcd035q3dg01_pdata); + if (ret) + pr_warning("da830_evm_init: lcd setup failed: %d\n", ret); + + gpio_direction_output(mux_mode, 0); +} +#else +static inline void da830_evm_init_lcdc(int mux_mode) { } +#endif + +static struct at24_platform_data da830_evm_i2c_eeprom_info = { + .byte_len = SZ_256K / 8, + .page_size = 64, + .flags = AT24_FLAG_ADDR16, + .setup = davinci_get_mac_addr, + .context = (void *)0x7f00, +}; + +static int __init da830_evm_ui_expander_setup(struct i2c_client *client, + int gpio, unsigned ngpio, void *context) +{ + gpio_request(gpio + 6, "UI MUX_MODE"); + + /* Drive mux mode low to match the default without UI card */ + gpio_direction_output(gpio + 6, 0); + + da830_evm_init_lcdc(gpio + 6); + + da830_evm_init_nand(gpio + 6); + + return 0; +} + +static int da830_evm_ui_expander_teardown(struct i2c_client *client, int gpio, + unsigned ngpio, void *context) +{ + gpio_free(gpio + 6); + return 0; +} + +static struct pcf857x_platform_data __initdata da830_evm_ui_expander_info = { + .gpio_base = DAVINCI_N_GPIO, + .setup = da830_evm_ui_expander_setup, + .teardown = da830_evm_ui_expander_teardown, +}; + +static struct i2c_board_info __initdata da830_evm_i2c_devices[] = { + { + I2C_BOARD_INFO("24c256", 0x50), + .platform_data = &da830_evm_i2c_eeprom_info, + }, + { + I2C_BOARD_INFO("tlv320aic3x", 0x18), + }, + { + I2C_BOARD_INFO("pcf8574", 0x3f), + .platform_data = &da830_evm_ui_expander_info, + }, +}; + +static struct davinci_i2c_platform_data da830_evm_i2c_0_pdata = { + .bus_freq = 100, /* kHz */ + .bus_delay = 0, /* usec */ +}; + static __init void da830_evm_init(void) { struct davinci_soc_info *soc_info = &davinci_soc_info; @@ -94,6 +502,8 @@ static __init void da830_evm_init(void) pr_warning("da830_evm_init: i2c0 registration failed: %d\n", ret); + da830_evm_usb_init(); + soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK; soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; soc_info->emac_pdata->rmii_en = 1; @@ -117,12 +527,18 @@ static __init void da830_evm_init(void) i2c_register_board_info(1, da830_evm_i2c_devices, ARRAY_SIZE(da830_evm_i2c_devices)); - ret = da8xx_pinmux_setup(da830_mcasp1_pins); + ret = da8xx_pinmux_setup(da830_evm_mcasp1_pins); if (ret) pr_warning("da830_evm_init: mcasp1 mux setup failed: %d\n", ret); - da8xx_init_mcasp(1, &da830_evm_snd_data); + da8xx_register_mcasp(1, &da830_evm_snd_data); + + da830_evm_init_mmc(); + + ret = da8xx_register_rtc(); + if (ret) + pr_warning("da830_evm_init: rtc setup failed: %d\n", ret); } #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -146,7 +562,7 @@ static void __init da830_evm_map_io(void) da830_init(); } -MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP L137 EVM") +MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM") .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DA8XX_DDR_BASE + 0x100), diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index c759d72494e0..62b98bffc158 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -12,36 +12,38 @@ * or implied. */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> #include <linux/console.h> #include <linux/i2c.h> #include <linux/i2c/at24.h> +#include <linux/i2c/pca953x.h> #include <linux/gpio.h> #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> +#include <linux/regulator/machine.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <mach/common.h> -#include <mach/irqs.h> #include <mach/cp_intc.h> #include <mach/da8xx.h> #include <mach/nand.h> +#include <mach/mux.h> #define DA850_EVM_PHY_MASK 0x1 #define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ +#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) -#define DA850_LCD_PWR_PIN GPIO_TO_PIN(8, 10) #define DA850_MMCSD_CD_PIN GPIO_TO_PIN(4, 0) #define DA850_MMCSD_WP_PIN GPIO_TO_PIN(4, 1) +#define DA850_MII_MDIO_CLKEN_PIN GPIO_TO_PIN(2, 6) + static struct mtd_partition da850_evm_norflash_partition[] = { { .name = "NOR filesystem", @@ -143,10 +145,149 @@ static struct platform_device da850_evm_nandflash_device = { .resource = da850_evm_nandflash_resource, }; +static struct platform_device *da850_evm_devices[] __initdata = { + &da850_evm_nandflash_device, + &da850_evm_norflash_device, +}; + +#define DA8XX_AEMIF_CE2CFG_OFFSET 0x10 +#define DA8XX_AEMIF_ASIZE_16BIT 0x1 + +static void __init da850_evm_init_nor(void) +{ + void __iomem *aemif_addr; + + aemif_addr = ioremap(DA8XX_AEMIF_CTL_BASE, SZ_32K); + + /* Configure data bus width of CS2 to 16 bit */ + writel(readl(aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET) | + DA8XX_AEMIF_ASIZE_16BIT, + aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET); + + iounmap(aemif_addr); +} + +static u32 ui_card_detected; + +#if defined(CONFIG_MMC_DAVINCI) || \ + defined(CONFIG_MMC_DAVINCI_MODULE) +#define HAS_MMC 1 +#else +#define HAS_MMC 0 +#endif + +static __init void da850_evm_setup_nor_nand(void) +{ + int ret = 0; + + if (ui_card_detected & !HAS_MMC) { + ret = da8xx_pinmux_setup(da850_nand_pins); + if (ret) + pr_warning("da850_evm_init: nand mux setup failed: " + "%d\n", ret); + + ret = da8xx_pinmux_setup(da850_nor_pins); + if (ret) + pr_warning("da850_evm_init: nor mux setup failed: %d\n", + ret); + + da850_evm_init_nor(); + + platform_add_devices(da850_evm_devices, + ARRAY_SIZE(da850_evm_devices)); + } +} + +#ifdef CONFIG_DA850_UI_RMII +static inline void da850_evm_setup_emac_rmii(int rmii_sel) +{ + struct davinci_soc_info *soc_info = &davinci_soc_info; + + soc_info->emac_pdata->rmii_en = 1; + gpio_set_value(rmii_sel, 0); +} +#else +static inline void da850_evm_setup_emac_rmii(int rmii_sel) { } +#endif + +static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio, + unsigned ngpio, void *c) +{ + int sel_a, sel_b, sel_c, ret; + + sel_a = gpio + 7; + sel_b = gpio + 6; + sel_c = gpio + 5; + + ret = gpio_request(sel_a, "sel_a"); + if (ret) { + pr_warning("Cannot open UI expander pin %d\n", sel_a); + goto exp_setup_sela_fail; + } + + ret = gpio_request(sel_b, "sel_b"); + if (ret) { + pr_warning("Cannot open UI expander pin %d\n", sel_b); + goto exp_setup_selb_fail; + } + + ret = gpio_request(sel_c, "sel_c"); + if (ret) { + pr_warning("Cannot open UI expander pin %d\n", sel_c); + goto exp_setup_selc_fail; + } + + /* deselect all functionalities */ + gpio_direction_output(sel_a, 1); + gpio_direction_output(sel_b, 1); + gpio_direction_output(sel_c, 1); + + ui_card_detected = 1; + pr_info("DA850/OMAP-L138 EVM UI card detected\n"); + + da850_evm_setup_nor_nand(); + + da850_evm_setup_emac_rmii(sel_a); + + return 0; + +exp_setup_selc_fail: + gpio_free(sel_b); +exp_setup_selb_fail: + gpio_free(sel_a); +exp_setup_sela_fail: + return ret; +} + +static int da850_evm_ui_expander_teardown(struct i2c_client *client, + unsigned gpio, unsigned ngpio, void *c) +{ + /* deselect all functionalities */ + gpio_set_value(gpio + 5, 1); + gpio_set_value(gpio + 6, 1); + gpio_set_value(gpio + 7, 1); + + gpio_free(gpio + 5); + gpio_free(gpio + 6); + gpio_free(gpio + 7); + + return 0; +} + +static struct pca953x_platform_data da850_evm_ui_expander_info = { + .gpio_base = DAVINCI_N_GPIO, + .setup = da850_evm_ui_expander_setup, + .teardown = da850_evm_ui_expander_teardown, +}; + static struct i2c_board_info __initdata da850_evm_i2c_devices[] = { { I2C_BOARD_INFO("tlv320aic3x", 0x18), - } + }, + { + I2C_BOARD_INFO("tca6416", 0x20), + .platform_data = &da850_evm_ui_expander_info, + }, }; static struct davinci_i2c_platform_data da850_evm_i2c_0_pdata = { @@ -158,11 +299,6 @@ static struct davinci_uart_config da850_evm_uart_config __initdata = { .enabled_uarts = 0x7, }; -static struct platform_device *da850_evm_devices[] __initdata = { - &da850_evm_nandflash_device, - &da850_evm_norflash_device, -}; - /* davinci da850 evm audio machine driver */ static u8 da850_iis_serializer_direction[] = { INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, @@ -198,6 +334,8 @@ static struct davinci_mmc_config da850_mmc_config = { .get_ro = da850_evm_mmc_get_ro, .get_cd = da850_evm_mmc_get_cd, .wires = 4, + .max_freq = 50000000, + .caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, .version = MMC_CTLR_VERSION_2, }; @@ -233,56 +371,227 @@ static int da850_lcd_hw_init(void) return 0; } -#define DA8XX_AEMIF_CE2CFG_OFFSET 0x10 -#define DA8XX_AEMIF_ASIZE_16BIT 0x1 +/* TPS65070 voltage regulator support */ -static void __init da850_evm_init_nor(void) -{ - void __iomem *aemif_addr; +/* 3.3V */ +struct regulator_consumer_supply tps65070_dcdc1_consumers[] = { + { + .supply = "usb0_vdda33", + }, + { + .supply = "usb1_vdda33", + }, +}; - aemif_addr = ioremap(DA8XX_AEMIF_CTL_BASE, SZ_32K); +/* 3.3V or 1.8V */ +struct regulator_consumer_supply tps65070_dcdc2_consumers[] = { + { + .supply = "dvdd3318_a", + }, + { + .supply = "dvdd3318_b", + }, + { + .supply = "dvdd3318_c", + }, +}; - /* Configure data bus width of CS2 to 16 bit */ - writel(readl(aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET) | - DA8XX_AEMIF_ASIZE_16BIT, - aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET); +/* 1.2V */ +struct regulator_consumer_supply tps65070_dcdc3_consumers[] = { + { + .supply = "cvdd", + }, +}; - iounmap(aemif_addr); -} +/* 1.8V LDO */ +struct regulator_consumer_supply tps65070_ldo1_consumers[] = { + { + .supply = "sata_vddr", + }, + { + .supply = "usb0_vdda18", + }, + { + .supply = "usb1_vdda18", + }, + { + .supply = "ddr_dvdd18", + }, +}; -#if defined(CONFIG_MTD_PHYSMAP) || \ - defined(CONFIG_MTD_PHYSMAP_MODULE) -#define HAS_NOR 1 -#else -#define HAS_NOR 0 -#endif +/* 1.2V LDO */ +struct regulator_consumer_supply tps65070_ldo2_consumers[] = { + { + .supply = "sata_vdd", + }, + { + .supply = "pll0_vdda", + }, + { + .supply = "pll1_vdda", + }, + { + .supply = "usbs_cvdd", + }, + { + .supply = "vddarnwa1", + }, +}; -#if defined(CONFIG_MMC_DAVINCI) || \ - defined(CONFIG_MMC_DAVINCI_MODULE) -#define HAS_MMC 1 -#else -#define HAS_MMC 0 -#endif +struct regulator_init_data tps65070_regulator_data[] = { + /* dcdc1 */ + { + .constraints = { + .min_uV = 3150000, + .max_uV = 3450000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65070_dcdc1_consumers), + .consumer_supplies = tps65070_dcdc1_consumers, + }, -static __init void da850_evm_init(void) + /* dcdc2 */ + { + .constraints = { + .min_uV = 1710000, + .max_uV = 3450000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65070_dcdc2_consumers), + .consumer_supplies = tps65070_dcdc2_consumers, + }, + + /* dcdc3 */ + { + .constraints = { + .min_uV = 950000, + .max_uV = 1320000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65070_dcdc3_consumers), + .consumer_supplies = tps65070_dcdc3_consumers, + }, + + /* ldo1 */ + { + .constraints = { + .min_uV = 1710000, + .max_uV = 1890000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65070_ldo1_consumers), + .consumer_supplies = tps65070_ldo1_consumers, + }, + + /* ldo2 */ + { + .constraints = { + .min_uV = 1140000, + .max_uV = 1320000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65070_ldo2_consumers), + .consumer_supplies = tps65070_ldo2_consumers, + }, +}; + +static struct i2c_board_info __initdata da850evm_tps65070_info[] = { + { + I2C_BOARD_INFO("tps6507x", 0x48), + .platform_data = &tps65070_regulator_data[0], + }, +}; + +static int __init pmic_tps65070_init(void) { - struct davinci_soc_info *soc_info = &davinci_soc_info; + return i2c_register_board_info(1, da850evm_tps65070_info, + ARRAY_SIZE(da850evm_tps65070_info)); +} + +static const short da850_evm_lcdc_pins[] = { + DA850_GPIO2_8, DA850_GPIO2_15, + -1 +}; + +static int __init da850_evm_config_emac(void) +{ + void __iomem *cfg_chip3_base; int ret; + u32 val; + struct davinci_soc_info *soc_info = &davinci_soc_info; + u8 rmii_en = soc_info->emac_pdata->rmii_en; + + if (!machine_is_davinci_da850_evm()) + return 0; + + cfg_chip3_base = DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG); + + val = __raw_readl(cfg_chip3_base); + + if (rmii_en) { + val |= BIT(8); + ret = da8xx_pinmux_setup(da850_rmii_pins); + pr_info("EMAC: RMII PHY configured, MII PHY will not be" + " functional\n"); + } else { + val &= ~BIT(8); + ret = da8xx_pinmux_setup(da850_cpgmac_pins); + pr_info("EMAC: MII PHY configured, RMII PHY will not be" + " functional\n"); + } - ret = da8xx_pinmux_setup(da850_nand_pins); if (ret) - pr_warning("da850_evm_init: nand mux setup failed: %d\n", + pr_warning("da850_evm_init: cpgmac/rmii mux setup failed: %d\n", ret); - ret = da8xx_pinmux_setup(da850_nor_pins); + /* configure the CFGCHIP3 register for RMII or MII */ + __raw_writel(val, cfg_chip3_base); + + ret = davinci_cfg_reg(DA850_GPIO2_6); if (ret) - pr_warning("da850_evm_init: nor mux setup failed: %d\n", + pr_warning("da850_evm_init:GPIO(2,6) mux setup " + "failed\n"); + + ret = gpio_request(DA850_MII_MDIO_CLKEN_PIN, "mdio_clk_en"); + if (ret) { + pr_warning("Cannot open GPIO %d\n", + DA850_MII_MDIO_CLKEN_PIN); + return ret; + } + + /* Enable/Disable MII MDIO clock */ + gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); + + soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; + soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; + + ret = da8xx_register_emac(); + if (ret) + pr_warning("da850_evm_init: emac registration failed: %d\n", ret); - da850_evm_init_nor(); + return 0; +} +device_initcall(da850_evm_config_emac); + +static __init void da850_evm_init(void) +{ + int ret; - platform_add_devices(da850_evm_devices, - ARRAY_SIZE(da850_evm_devices)); + ret = pmic_tps65070_init(); + if (ret) + pr_warning("da850_evm_init: TPS65070 PMIC init failed: %d\n", + ret); ret = da8xx_register_edma(); if (ret) @@ -299,19 +608,6 @@ static __init void da850_evm_init(void) pr_warning("da850_evm_init: i2c0 registration failed: %d\n", ret); - soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; - soc_info->emac_pdata->rmii_en = 0; - - ret = da8xx_pinmux_setup(da850_cpgmac_pins); - if (ret) - pr_warning("da850_evm_init: cpgmac mux setup failed: %d\n", - ret); - - ret = da8xx_register_emac(); - if (ret) - pr_warning("da850_evm_init: emac registration failed: %d\n", - ret); ret = da8xx_register_watchdog(); if (ret) @@ -319,11 +615,6 @@ static __init void da850_evm_init(void) ret); if (HAS_MMC) { - if (HAS_NOR) - pr_warning("WARNING: both NOR Flash and MMC/SD are " - "enabled, but they share AEMIF pins.\n" - "\tDisable one of them.\n"); - ret = da8xx_pinmux_setup(da850_mmcsd0_pins); if (ret) pr_warning("da850_evm_init: mmcsd0 mux setup failed:" @@ -365,22 +656,42 @@ static __init void da850_evm_init(void) pr_warning("da850_evm_init: mcasp mux setup failed: %d\n", ret); - da8xx_init_mcasp(0, &da850_evm_snd_data); + da8xx_register_mcasp(0, &da850_evm_snd_data); ret = da8xx_pinmux_setup(da850_lcdcntl_pins); if (ret) pr_warning("da850_evm_init: lcdcntl mux setup failed: %d\n", ret); + /* Handle board specific muxing for LCD here */ + ret = da8xx_pinmux_setup(da850_evm_lcdc_pins); + if (ret) + pr_warning("da850_evm_init: evm specific lcd mux setup " + "failed: %d\n", ret); + ret = da850_lcd_hw_init(); if (ret) pr_warning("da850_evm_init: lcd initialization failed: %d\n", ret); - ret = da8xx_register_lcdc(); + ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata); if (ret) pr_warning("da850_evm_init: lcdc registration failed: %d\n", ret); + + ret = da8xx_register_rtc(); + if (ret) + pr_warning("da850_evm_init: rtc setup failed: %d\n", ret); + + ret = da850_register_cpufreq(); + if (ret) + pr_warning("da850_evm_init: cpufreq registration failed: %d\n", + ret); + + ret = da8xx_register_cpuidle(); + if (ret) + pr_warning("da850_evm_init: cpuidle registration failed: %d\n", + ret); } #ifdef CONFIG_SERIAL_8250_CONSOLE diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index 77e806798822..a9b650dcc172 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -9,15 +9,13 @@ * or implied. */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> #include <linux/i2c.h> -#include <linux/io.h> #include <linux/gpio.h> #include <linux/clk.h> #include <linux/videodev2.h> @@ -25,20 +23,15 @@ #include <linux/spi/spi.h> #include <linux/spi/eeprom.h> -#include <asm/setup.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/flash.h> -#include <mach/hardware.h> #include <mach/dm355.h> -#include <mach/psc.h> -#include <mach/common.h> #include <mach/i2c.h> #include <mach/serial.h> #include <mach/nand.h> #include <mach/mmc.h> +#include <mach/usb.h> #define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e10000 #define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 @@ -86,8 +79,9 @@ static struct davinci_nand_pdata davinci_nand_data = { .mask_chipsel = BIT(14), .parts = davinci_nand_partitions, .nr_parts = ARRAY_SIZE(davinci_nand_partitions), - .ecc_mode = NAND_ECC_HW_SYNDROME, + .ecc_mode = NAND_ECC_HW, .options = NAND_USE_FLASH_BBT, + .ecc_bits = 4, }; static struct resource davinci_nand_resources[] = { @@ -344,7 +338,7 @@ static __init void dm355_evm_init(void) gpio_request(2, "usb_id_toggle"); gpio_direction_output(2, USB_ID_VALUE); /* irlml6401 switches over 1A in under 8 msec */ - setup_usb(500, 8); + davinci_setup_usb(1000, 8); davinci_setup_mmc(0, &dm355evm_mmc_config); davinci_setup_mmc(1, &dm355evm_mmc_config); diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c index 84ad5d161a87..21f32eb41e8c 100644 --- a/arch/arm/mach-davinci/board-dm355-leopard.c +++ b/arch/arm/mach-davinci/board-dm355-leopard.c @@ -8,34 +8,27 @@ * warranty of any kind, whether express or implied. */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> #include <linux/i2c.h> -#include <linux/io.h> #include <linux/gpio.h> #include <linux/clk.h> #include <linux/spi/spi.h> #include <linux/spi/eeprom.h> -#include <asm/setup.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/flash.h> -#include <mach/hardware.h> #include <mach/dm355.h> -#include <mach/psc.h> -#include <mach/common.h> #include <mach/i2c.h> #include <mach/serial.h> #include <mach/nand.h> #include <mach/mmc.h> +#include <mach/usb.h> #define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e10000 #define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 @@ -270,7 +263,7 @@ static __init void dm355_leopard_init(void) gpio_request(2, "usb_id_toggle"); gpio_direction_output(2, USB_ID_VALUE); /* irlml6401 switches over 1A in under 8 msec */ - setup_usb(500, 8); + davinci_setup_usb(1000, 8); davinci_setup_mmc(0, &dm355leopard_mmc_config); davinci_setup_mmc(1, &dm355leopard_mmc_config); diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 52dd8046b305..289fe1b7d25a 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -13,9 +13,8 @@ * GNU General Public License for more details. */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/i2c.h> #include <linux/io.h> #include <linux/clk.h> @@ -24,20 +23,19 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> -#include <asm/setup.h> +#include <linux/input.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> + #include <mach/mux.h> -#include <mach/hardware.h> #include <mach/dm365.h> -#include <mach/psc.h> #include <mach/common.h> #include <mach/i2c.h> #include <mach/serial.h> #include <mach/mmc.h> #include <mach/nand.h> - +#include <mach/keyscan.h> static inline int have_imager(void) { @@ -144,6 +142,7 @@ static struct davinci_nand_pdata davinci_nand_data = { .nr_parts = ARRAY_SIZE(davinci_nand_partitions), .ecc_mode = NAND_ECC_HW, .options = NAND_USE_FLASH_BBT, + .ecc_bits = 4, }; static struct resource davinci_nand_resources[] = { @@ -176,11 +175,16 @@ static struct at24_platform_data eeprom_info = { .context = (void *)0x7f00, }; +static struct snd_platform_data dm365_evm_snd_data; + static struct i2c_board_info i2c_info[] = { { I2C_BOARD_INFO("24c256", 0x50), .platform_data = &eeprom_info, }, + { + I2C_BOARD_INFO("tlv320aic3x", 0x18), + }, }; static struct davinci_i2c_platform_data i2c_pdata = { @@ -188,6 +192,38 @@ static struct davinci_i2c_platform_data i2c_pdata = { .bus_delay = 0 /* usec */, }; +#ifdef CONFIG_KEYBOARD_DAVINCI +static unsigned short dm365evm_keymap[] = { + KEY_KP2, + KEY_LEFT, + KEY_EXIT, + KEY_DOWN, + KEY_ENTER, + KEY_UP, + KEY_KP1, + KEY_RIGHT, + KEY_MENU, + KEY_RECORD, + KEY_REWIND, + KEY_KPMINUS, + KEY_STOP, + KEY_FASTFORWARD, + KEY_KPPLUS, + KEY_PLAYPAUSE, + 0 +}; + +static struct davinci_ks_platform_data dm365evm_ks_data = { + .keymap = dm365evm_keymap, + .keymapsize = ARRAY_SIZE(dm365evm_keymap), + .rep = 1, + /* Scan period = strobe + interval */ + .strobe = 0x5, + .interval = 0x2, + .matrix_type = DAVINCI_KEYSCAN_MATRIX_4X4, +}; +#endif + static int cpld_mmc_get_cd(int module) { if (!cpld) @@ -472,6 +508,13 @@ static __init void dm365_evm_init(void) /* maybe setup mmc1/etc ... _after_ mmc0 */ evm_init_cpld(); + + dm365_init_asp(&dm365_evm_snd_data); + dm365_init_rtc(); + +#ifdef CONFIG_KEYBOARD_DAVINCI + dm365_init_ks(&dm365evm_ks_data); +#endif } static __init void dm365_evm_irq_init(void) diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 1213a0087ad4..fd0398bc6db3 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -9,45 +9,34 @@ * or implied. */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> #include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/gpio.h> -#include <linux/leds.h> -#include <linux/memory.h> - #include <linux/i2c.h> #include <linux/i2c/pcf857x.h> #include <linux/i2c/at24.h> -#include <linux/etherdevice.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> -#include <linux/io.h> #include <linux/phy.h> #include <linux/clk.h> #include <linux/videodev2.h> #include <media/tvp514x.h> -#include <asm/setup.h> #include <asm/mach-types.h> - #include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/flash.h> #include <mach/dm644x.h> #include <mach/common.h> #include <mach/i2c.h> #include <mach/serial.h> #include <mach/mux.h> -#include <mach/psc.h> #include <mach/nand.h> #include <mach/mmc.h> -#include <mach/emac.h> +#include <mach/usb.h> #define DM644X_EVM_PHY_MASK (0x2) #define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ @@ -477,7 +466,7 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) /* irlml6401 switches over 1A, in under 8 msec; * now it can be managed by nDRV_VBUS ... */ - setup_usb(500, 8); + davinci_setup_usb(1000, 8); return 0; } diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 24e0e13b1492..8d0b0e01c59b 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -17,38 +17,28 @@ **************************************************************************/ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/fs.h> -#include <linux/major.h> -#include <linux/root_dev.h> -#include <linux/dma-mapping.h> -#include <linux/serial.h> -#include <linux/serial_8250.h> #include <linux/leds.h> #include <linux/gpio.h> -#include <linux/io.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/i2c/at24.h> #include <linux/i2c/pcf857x.h> -#include <linux/etherdevice.h> #include <media/tvp514x.h> -#include <asm/setup.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/flash.h> #include <mach/dm646x.h> #include <mach/common.h> -#include <mach/psc.h> #include <mach/serial.h> #include <mach/i2c.h> -#include <mach/mmc.h> -#include <mach/emac.h> +#include <mach/nand.h> #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) @@ -57,6 +47,11 @@ #define HAS_ATA 0 #endif +#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x20008000 +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x42000000 + +#define NAND_BLOCK_SIZE SZ_128K + /* CPLD Register 0 bits to control ATA */ #define DM646X_EVM_ATA_RST BIT(0) #define DM646X_EVM_ATA_PWD BIT(1) @@ -92,6 +87,63 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; +/* Note: We are setting first partition as 'bootloader' constituting UBL, U-Boot + * and U-Boot environment this avoids dependency on any particular combination + * of UBL, U-Boot or flashing tools etc. + */ +static struct mtd_partition davinci_nand_partitions[] = { + { + /* UBL, U-Boot with environment */ + .name = "bootloader", + .offset = MTDPART_OFS_APPEND, + .size = 16 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_4M, + .mask_flags = 0, + }, { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0, + } +}; + +static struct davinci_nand_pdata davinci_nand_data = { + .mask_cle = 0x80000, + .mask_ale = 0x40000, + .parts = davinci_nand_partitions, + .nr_parts = ARRAY_SIZE(davinci_nand_partitions), + .ecc_mode = NAND_ECC_HW, + .options = 0, +}; + +static struct resource davinci_nand_resources[] = { + { + .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, + .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, + .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device davinci_nand_device = { + .name = "davinci_nand", + .id = 0, + + .num_resources = ARRAY_SIZE(davinci_nand_resources), + .resource = davinci_nand_resources, + + .dev = { + .platform_data = &davinci_nand_data, + }, +}; + /* CPLD Register 0 Client: used for I/O Control */ static int cpld_reg0_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -142,7 +194,7 @@ static struct gpio_led evm_leds[] = { { .name = "DS4", .active_low = 1, }, }; -static __initconst struct gpio_led_platform_data evm_led_data = { +static const struct gpio_led_platform_data evm_led_data = { .num_leds = ARRAY_SIZE(evm_leds), .leds = evm_leds, }; @@ -647,6 +699,8 @@ static __init void evm_init(void) dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); dm646x_init_mcasp1(&dm646x_evm_snd_data[1]); + platform_device_register(&davinci_nand_device); + if (HAS_ATA) dm646x_init_ide(); diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c new file mode 100644 index 000000000000..bd9ca079b69d --- /dev/null +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -0,0 +1,323 @@ +/* + * Neuros Technologies OSD2 board support + * + * Modified from original 644X-EVM board support. + * 2008 (c) Neuros Technology, LLC. + * 2009 (c) Jorge Luis Zapata Muga <jorgeluis.zapata@gmail.com> + * 2009 (c) Andrey A. Porodko <Andrey.Porodko@gmail.com> + * + * The Neuros OSD 2.0 is the hardware component of the Neuros Open + * Internet Television Platform. Hardware is very close to TI + * DM644X-EVM board. It has: + * DM6446M02 module with 256MB NAND, 256MB RAM, TLV320AIC32 AIC, + * USB, Ethernet, SD/MMC, UART, THS8200, TVP7000 for video. + * Additionaly realtime clock, IR remote control receiver, + * IR Blaster based on MSP430 (firmware although is different + * from used in DM644X-EVM), internal ATA-6 3.5” HDD drive + * with PATA interface, two muxed red-green leds. + * + * For more information please refer to + * http://wiki.neurostechnology.com/index.php/OSD_2.0_HD + * + * 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/platform_device.h> +#include <linux/gpio.h> +#include <linux/mtd/partitions.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +#include <mach/dm644x.h> +#include <mach/i2c.h> +#include <mach/serial.h> +#include <mach/mux.h> +#include <mach/nand.h> +#include <mach/mmc.h> +#include <mach/usb.h> + +#define NEUROS_OSD2_PHY_MASK 0x2 +#define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ + +#define DAVINCI_CFC_ATA_BASE 0x01C66000 + +#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 + +#define LXT971_PHY_ID 0x001378e2 +#define LXT971_PHY_MASK 0xfffffff0 + +#define NTOSD2_AUDIOSOC_I2C_ADDR 0x18 +#define NTOSD2_MSP430_I2C_ADDR 0x59 +#define NTOSD2_MSP430_IRQ 2 + +/* Neuros OSD2 has a Samsung 256 MByte NAND flash (Dev ID of 0xAA, + * 2048 blocks in the device, 64 pages per block, 2048 bytes per + * page. + */ + +#define NAND_BLOCK_SIZE SZ_128K + +struct mtd_partition davinci_ntosd2_nandflash_partition[] = { + { + /* UBL (a few copies) plus U-Boot */ + .name = "bootloader", + .offset = 0, + .size = 15 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + /* U-Boot environment */ + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = 1 * NAND_BLOCK_SIZE, + .mask_flags = 0, + }, { + /* Kernel */ + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_4M, + .mask_flags = 0, + }, { + /* File System */ + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0, + } + /* A few blocks at end hold a flash Bad Block Table. */ +}; + +static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = { + .parts = davinci_ntosd2_nandflash_partition, + .nr_parts = ARRAY_SIZE(davinci_ntosd2_nandflash_partition), + .ecc_mode = NAND_ECC_HW, + .options = NAND_USE_FLASH_BBT, +}; + +static struct resource davinci_ntosd2_nandflash_resource[] = { + { + .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, + .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, + .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device davinci_ntosd2_nandflash_device = { + .name = "davinci_nand", + .id = 0, + .dev = { + .platform_data = &davinci_ntosd2_nandflash_data, + }, + .num_resources = ARRAY_SIZE(davinci_ntosd2_nandflash_resource), + .resource = davinci_ntosd2_nandflash_resource, +}; + +static u64 davinci_fb_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device davinci_fb_device = { + .name = "davincifb", + .id = -1, + .dev = { + .dma_mask = &davinci_fb_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = 0, +}; + +static struct resource ide_resources[] = { + { + .start = DAVINCI_CFC_ATA_BASE, + .end = DAVINCI_CFC_ATA_BASE + 0x7ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_IDE, + .end = IRQ_IDE, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ide_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device ide_dev = { + .name = "palm_bk3710", + .id = -1, + .resource = ide_resources, + .num_resources = ARRAY_SIZE(ide_resources), + .dev = { + .dma_mask = &ide_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +static struct snd_platform_data dm644x_ntosd2_snd_data; + +static struct gpio_led ntosd2_leds[] = { + { .name = "led1_green", .gpio = GPIO(10), }, + { .name = "led1_red", .gpio = GPIO(11), }, + { .name = "led2_green", .gpio = GPIO(12), }, + { .name = "led2_red", .gpio = GPIO(13), }, +}; + +static struct gpio_led_platform_data ntosd2_leds_data = { + .num_leds = ARRAY_SIZE(ntosd2_leds), + .leds = ntosd2_leds, +}; + +static struct platform_device ntosd2_leds_dev = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &ntosd2_leds_data, + }, +}; + + +static struct platform_device *davinci_ntosd2_devices[] __initdata = { + &davinci_fb_device, + &ntosd2_leds_dev, +}; + +static struct davinci_uart_config uart_config __initdata = { + .enabled_uarts = (1 << 0), +}; + +static void __init davinci_ntosd2_map_io(void) +{ + dm644x_init(); +} + +/* + I2C initialization +*/ +static struct davinci_i2c_platform_data ntosd2_i2c_pdata = { + .bus_freq = 20 /* kHz */, + .bus_delay = 100 /* usec */, +}; + +static struct i2c_board_info __initdata ntosd2_i2c_info[] = { +}; + +static int ntosd2_init_i2c(void) +{ + int status; + + davinci_init_i2c(&ntosd2_i2c_pdata); + status = gpio_request(NTOSD2_MSP430_IRQ, ntosd2_i2c_info[0].type); + if (status == 0) { + status = gpio_direction_input(NTOSD2_MSP430_IRQ); + if (status == 0) { + status = gpio_to_irq(NTOSD2_MSP430_IRQ); + if (status > 0) { + ntosd2_i2c_info[0].irq = status; + i2c_register_board_info(1, + ntosd2_i2c_info, + ARRAY_SIZE(ntosd2_i2c_info)); + } + } + } + return status; +} + +static struct davinci_mmc_config davinci_ntosd2_mmc_config = { + .wires = 4, + .version = MMC_CTLR_VERSION_1 +}; + + +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) +#define HAS_ATA 1 +#else +#define HAS_ATA 0 +#endif + +#if defined(CONFIG_MTD_NAND_DAVINCI) || \ + defined(CONFIG_MTD_NAND_DAVINCI_MODULE) +#define HAS_NAND 1 +#else +#define HAS_NAND 0 +#endif + +static __init void davinci_ntosd2_init(void) +{ + struct clk *aemif_clk; + struct davinci_soc_info *soc_info = &davinci_soc_info; + int status; + + aemif_clk = clk_get(NULL, "aemif"); + clk_enable(aemif_clk); + + if (HAS_ATA) { + if (HAS_NAND) + pr_warning("WARNING: both IDE and Flash are " + "enabled, but they share AEMIF pins.\n" + "\tDisable IDE for NAND/NOR support.\n"); + davinci_cfg_reg(DM644X_HPIEN_DISABLE); + davinci_cfg_reg(DM644X_ATAEN); + davinci_cfg_reg(DM644X_HDIREN); + platform_device_register(&ide_dev); + } else if (HAS_NAND) { + davinci_cfg_reg(DM644X_HPIEN_DISABLE); + davinci_cfg_reg(DM644X_ATAEN_DISABLE); + + /* only one device will be jumpered and detected */ + if (HAS_NAND) + platform_device_register( + &davinci_ntosd2_nandflash_device); + } + + platform_add_devices(davinci_ntosd2_devices, + ARRAY_SIZE(davinci_ntosd2_devices)); + + /* Initialize I2C interface specific for this board */ + status = ntosd2_init_i2c(); + if (status < 0) + pr_warning("davinci_ntosd2_init: msp430 irq setup failed:" + " %d\n", status); + + davinci_serial_init(&uart_config); + dm644x_init_asp(&dm644x_ntosd2_snd_data); + + soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK; + soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY; + + davinci_setup_usb(1000, 8); + /* + * Mux the pins to be GPIOs, VLYNQEN is already done at startup. + * The AEAWx are five new AEAW pins that can be muxed by separately. + * They are a bitmask for GPIO management. According TI + * documentation (http://www.ti.com/lit/gpn/tms320dm6446) to employ + * gpio(10,11,12,13) for leds any combination of bits works except + * four last. So we are to reset all five. + */ + davinci_cfg_reg(DM644X_AEAW0); + davinci_cfg_reg(DM644X_AEAW1); + davinci_cfg_reg(DM644X_AEAW2); + davinci_cfg_reg(DM644X_AEAW3); + davinci_cfg_reg(DM644X_AEAW4); + + davinci_setup_mmc(0, &davinci_ntosd2_mmc_config); +} + +static __init void davinci_ntosd2_irq_init(void) +{ + davinci_irq_init(); +} + +MACHINE_START(NEUROS_OSD2, "Neuros OSD2") + /* Maintainer: Neuros Technologies <neuros@groups.google.com> */ + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DAVINCI_DDR_BASE + 0x100), + .map_io = davinci_ntosd2_map_io, + .init_irq = davinci_ntosd2_irq_init, + .timer = &davinci_timer, + .init_machine = davinci_ntosd2_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 7acdfd8ac071..08d373bfcc8a 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -23,35 +23,24 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/dma-mapping.h> #include <linux/platform_device.h> -#include <linux/gpio.h> - #include <linux/i2c.h> #include <linux/i2c/at24.h> -#include <linux/etherdevice.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> -#include <linux/io.h> -#include <asm/setup.h> #include <asm/mach-types.h> - #include <asm/mach/arch.h> -#include <asm/mach/map.h> #include <asm/mach/flash.h> #include <mach/dm644x.h> #include <mach/common.h> #include <mach/i2c.h> #include <mach/serial.h> -#include <mach/psc.h> #include <mach/mux.h> +#include <mach/usb.h> #define SFFSDR_PHY_MASK (0x2) #define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ @@ -107,11 +96,6 @@ static struct platform_device davinci_sffsdr_nandflash_device = { .resource = davinci_sffsdr_nandflash_resource, }; -static struct emac_platform_data sffsdr_emac_pdata = { - .phy_mask = SFFSDR_PHY_MASK, - .mdio_max_freq = SFFSDR_MDIO_FREQUENCY, -}; - static struct at24_platform_data eeprom_info = { .byte_len = (64*1024) / 8, .page_size = 32, @@ -164,7 +148,7 @@ static __init void davinci_sffsdr_init(void) davinci_serial_init(&uart_config); soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; - setup_usb(0, 0); /* We support only peripheral mode. */ + davinci_setup_usb(0, 0); /* We support only peripheral mode. */ /* mux VLYNQ pins */ davinci_cfg_reg(DM644X_VLYNQEN); diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 83d54d50b5ea..baece65cb9c0 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -17,8 +17,8 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/mutex.h> -#include <linux/platform_device.h> #include <linux/io.h> +#include <linux/delay.h> #include <mach/hardware.h> @@ -42,8 +42,7 @@ static void __clk_enable(struct clk *clk) if (clk->parent) __clk_enable(clk->parent); if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) - davinci_psc_config(psc_domain(clk), clk->psc_ctlr, - clk->lpsc, 1); + davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1); } static void __clk_disable(struct clk *clk) @@ -51,8 +50,7 @@ static void __clk_disable(struct clk *clk) if (WARN_ON(clk->usecount == 0)) return; if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) - davinci_psc_config(psc_domain(clk), clk->psc_ctlr, - clk->lpsc, 0); + davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); if (clk->parent) __clk_disable(clk->parent); } @@ -99,20 +97,74 @@ long clk_round_rate(struct clk *clk, unsigned long rate) if (clk == NULL || IS_ERR(clk)) return -EINVAL; + if (clk->round_rate) + return clk->round_rate(clk, rate); + return clk->rate; } EXPORT_SYMBOL(clk_round_rate); +/* Propagate rate to children */ +static void propagate_rate(struct clk *root) +{ + struct clk *clk; + + list_for_each_entry(clk, &root->children, childnode) { + if (clk->recalc) + clk->rate = clk->recalc(clk); + propagate_rate(clk); + } +} + int clk_set_rate(struct clk *clk, unsigned long rate) { + unsigned long flags; + int ret = -EINVAL; + if (clk == NULL || IS_ERR(clk)) - return -EINVAL; + return ret; - /* changing the clk rate is not supported */ - return -EINVAL; + spin_lock_irqsave(&clockfw_lock, flags); + if (clk->set_rate) + ret = clk->set_rate(clk, rate); + if (ret == 0) { + if (clk->recalc) + clk->rate = clk->recalc(clk); + propagate_rate(clk); + } + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; } EXPORT_SYMBOL(clk_set_rate); +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + /* Cannot change parent on enabled clock */ + if (WARN_ON(clk->usecount)) + return -EINVAL; + + mutex_lock(&clocks_mutex); + clk->parent = parent; + list_del_init(&clk->childnode); + list_add(&clk->childnode, &clk->parent->children); + mutex_unlock(&clocks_mutex); + + spin_lock_irqsave(&clockfw_lock, flags); + if (clk->recalc) + clk->rate = clk->recalc(clk); + propagate_rate(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} +EXPORT_SYMBOL(clk_set_parent); + int clk_register(struct clk *clk) { if (clk == NULL || IS_ERR(clk)) @@ -123,16 +175,24 @@ int clk_register(struct clk *clk) clk->name, clk->parent->name)) return -EINVAL; + INIT_LIST_HEAD(&clk->children); + mutex_lock(&clocks_mutex); list_add_tail(&clk->node, &clocks); + if (clk->parent) + list_add_tail(&clk->childnode, &clk->parent->children); mutex_unlock(&clocks_mutex); /* If rate is already set, use it */ if (clk->rate) return 0; + /* Else, see if there is a way to calculate it */ + if (clk->recalc) + clk->rate = clk->recalc(clk); + /* Otherwise, default to parent rate */ - if (clk->parent) + else if (clk->parent) clk->rate = clk->parent->rate; return 0; @@ -146,6 +206,7 @@ void clk_unregister(struct clk *clk) mutex_lock(&clocks_mutex); list_del(&clk->node); + list_del(&clk->childnode); mutex_unlock(&clocks_mutex); } EXPORT_SYMBOL(clk_unregister); @@ -166,11 +227,11 @@ static int __init clk_disable_unused(void) continue; /* ignore if in Disabled or SwRstDisable states */ - if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc)) + if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc)) continue; pr_info("Clocks: disable unused %s\n", ck->name); - davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0); + davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0); } spin_unlock_irq(&clockfw_lock); @@ -179,50 +240,62 @@ static int __init clk_disable_unused(void) late_initcall(clk_disable_unused); #endif -static void clk_sysclk_recalc(struct clk *clk) +static unsigned long clk_sysclk_recalc(struct clk *clk) { u32 v, plldiv; struct pll_data *pll; + unsigned long rate = clk->rate; /* If this is the PLL base clock, no more calculations needed */ if (clk->pll_data) - return; + return rate; if (WARN_ON(!clk->parent)) - return; + return rate; - clk->rate = clk->parent->rate; + rate = clk->parent->rate; /* Otherwise, the parent must be a PLL */ if (WARN_ON(!clk->parent->pll_data)) - return; + return rate; pll = clk->parent->pll_data; /* If pre-PLL, source clock is before the multiplier and divider(s) */ if (clk->flags & PRE_PLL) - clk->rate = pll->input_rate; + rate = pll->input_rate; if (!clk->div_reg) - return; + return rate; v = __raw_readl(pll->base + clk->div_reg); if (v & PLLDIV_EN) { plldiv = (v & PLLDIV_RATIO_MASK) + 1; if (plldiv) - clk->rate /= plldiv; + rate /= plldiv; } + + return rate; +} + +static unsigned long clk_leafclk_recalc(struct clk *clk) +{ + if (WARN_ON(!clk->parent)) + return clk->rate; + + return clk->parent->rate; } -static void __init clk_pll_init(struct clk *clk) +static unsigned long clk_pllclk_recalc(struct clk *clk) { u32 ctrl, mult = 1, prediv = 1, postdiv = 1; u8 bypass; struct pll_data *pll = clk->pll_data; + unsigned long rate = clk->rate; pll->base = IO_ADDRESS(pll->phys_base); ctrl = __raw_readl(pll->base + PLLCTL); - clk->rate = pll->input_rate = clk->parent->rate; + rate = pll->input_rate = clk->parent->rate; if (ctrl & PLLCTL_PLLEN) { bypass = 0; @@ -255,9 +328,9 @@ static void __init clk_pll_init(struct clk *clk) } if (!bypass) { - clk->rate /= prediv; - clk->rate *= mult; - clk->rate /= postdiv; + rate /= prediv; + rate *= mult; + rate /= postdiv; } pr_debug("PLL%d: input = %lu MHz [ ", @@ -270,8 +343,90 @@ static void __init clk_pll_init(struct clk *clk) pr_debug("* %d ", mult); if (postdiv > 1) pr_debug("/ %d ", postdiv); - pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); + pr_debug("] --> %lu MHz output.\n", rate / 1000000); + + return rate; +} + +/** + * davinci_set_pllrate - set the output rate of a given PLL. + * + * Note: Currently tested to work with OMAP-L138 only. + * + * @pll: pll whose rate needs to be changed. + * @prediv: The pre divider value. Passing 0 disables the pre-divider. + * @pllm: The multiplier value. Passing 0 leads to multiply-by-one. + * @postdiv: The post divider value. Passing 0 disables the post-divider. + */ +int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, + unsigned int mult, unsigned int postdiv) +{ + u32 ctrl; + unsigned int locktime; + + if (pll->base == NULL) + return -EINVAL; + + /* + * PLL lock time required per OMAP-L138 datasheet is + * (2000 * prediv)/sqrt(pllm) OSCIN cycles. We approximate sqrt(pllm) + * as 4 and OSCIN cycle as 25 MHz. + */ + if (prediv) { + locktime = ((2000 * prediv) / 100); + prediv = (prediv - 1) | PLLDIV_EN; + } else { + locktime = 20; + } + if (postdiv) + postdiv = (postdiv - 1) | PLLDIV_EN; + if (mult) + mult = mult - 1; + + ctrl = __raw_readl(pll->base + PLLCTL); + + /* Switch the PLL to bypass mode */ + ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN); + __raw_writel(ctrl, pll->base + PLLCTL); + + /* + * Wait for 4 OSCIN/CLKIN cycles to ensure that the PLLC has switched + * to bypass mode. Delay of 1us ensures we are good for all > 4MHz + * OSCIN/CLKIN inputs. Typically the input is ~25MHz. + */ + udelay(1); + + /* Reset and enable PLL */ + ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS); + __raw_writel(ctrl, pll->base + PLLCTL); + + if (pll->flags & PLL_HAS_PREDIV) + __raw_writel(prediv, pll->base + PREDIV); + + __raw_writel(mult, pll->base + PLLM); + + if (pll->flags & PLL_HAS_POSTDIV) + __raw_writel(postdiv, pll->base + POSTDIV); + + /* + * Wait for PLL to reset properly, OMAP-L138 datasheet says + * 'min' time = 125ns + */ + udelay(1); + + /* Bring PLL out of reset */ + ctrl |= PLLCTL_PLLRST; + __raw_writel(ctrl, pll->base + PLLCTL); + + udelay(locktime); + + /* Remove PLL from bypass mode */ + ctrl |= PLLCTL_PLLEN; + __raw_writel(ctrl, pll->base + PLLCTL); + + return 0; } +EXPORT_SYMBOL(davinci_set_pllrate); int __init davinci_clk_init(struct davinci_clk *clocks) { @@ -281,12 +436,23 @@ int __init davinci_clk_init(struct davinci_clk *clocks) for (c = clocks; c->lk.clk; c++) { clk = c->lk.clk; - if (clk->pll_data) - clk_pll_init(clk); + if (!clk->recalc) { + + /* Check if clock is a PLL */ + if (clk->pll_data) + clk->recalc = clk_pllclk_recalc; + + /* Else, if it is a PLL-derived clock */ + else if (clk->flags & CLK_PLL) + clk->recalc = clk_sysclk_recalc; + + /* Otherwise, it is a leaf clock (PSC clock) */ + else if (clk->parent) + clk->recalc = clk_leafclk_recalc; + } - /* Calculate rates for PLL-derived clocks */ - else if (clk->flags & CLK_PLL) - clk_sysclk_recalc(clk); + if (clk->recalc) + clk->rate = clk->recalc(clk); if (clk->lpsc) clk->flags |= CLK_PSC; @@ -352,9 +518,8 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) /* REVISIT show device associations too */ /* cost is now small, but not linear... */ - list_for_each_entry(clk, &clocks, node) { - if (clk->parent == parent) - dump_clock(s, nest + NEST_DELTA, clk); + list_for_each_entry(clk, &parent->children, childnode) { + dump_clock(s, nest + NEST_DELTA, clk); } } diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 27233cb4a2fb..c92d77a3008d 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -22,6 +22,10 @@ /* PLL/Reset register offsets */ #define PLLCTL 0x100 #define PLLCTL_PLLEN BIT(0) +#define PLLCTL_PLLPWRDN BIT(1) +#define PLLCTL_PLLRST BIT(3) +#define PLLCTL_PLLDIS BIT(4) +#define PLLCTL_PLLENSRC BIT(5) #define PLLCTL_CLKMODE BIT(8) #define PLLM 0x110 @@ -65,15 +69,20 @@ struct clk { const char *name; unsigned long rate; u8 usecount; - u8 flags; u8 lpsc; - u8 psc_ctlr; + u8 gpsc; + u32 flags; struct clk *parent; + struct list_head children; /* list of children */ + struct list_head childnode; /* parent's child list node */ struct pll_data *pll_data; u32 div_reg; + unsigned long (*recalc) (struct clk *); + int (*set_rate) (struct clk *clk, unsigned long rate); + int (*round_rate) (struct clk *clk, unsigned long rate); }; -/* Clock flags */ +/* Clock flags: SoC-specific flags start at BIT(16) */ #define ALWAYS_ENABLED BIT(1) #define CLK_PSC BIT(2) #define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */ @@ -94,6 +103,8 @@ struct davinci_clk { } int davinci_clk_init(struct davinci_clk *clocks); +int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, + unsigned int mult, unsigned int postdiv); extern struct platform_device davinci_wdt_device; diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index 61ede19c6b54..c2de94cde56a 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -86,6 +86,8 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) dip = davinci_get_id(davinci_soc_info.jtag_id); if (!dip) { ret = -EINVAL; + pr_err("Unknown DaVinci JTAG ID 0x%x\n", + davinci_soc_info.jtag_id); goto err; } @@ -104,5 +106,5 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) return; err: - pr_err("davinci_common_init: SoC Initialization failed\n"); + panic("davinci_common_init: SoC Initialization failed\n"); } diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index 96c8e97a7deb..52b287cf3a42 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -10,9 +10,6 @@ */ #include <linux/init.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> #include <linux/irq.h> #include <linux/io.h> diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c new file mode 100644 index 000000000000..d3fa6de1e20f --- /dev/null +++ b/arch/arm/mach-davinci/cpufreq.c @@ -0,0 +1,226 @@ +/* + * CPU frequency scaling for DaVinci + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * Based on linux/arch/arm/plat-omap/cpu-omap.c. Original Copyright follows: + * + * Copyright (C) 2005 Nokia Corporation + * Written by Tony Lindgren <tony@atomide.com> + * + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Updated to support OMAP3 + * Rajendra Nayak <rnayak@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/types.h> +#include <linux/cpufreq.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/platform_device.h> + +#include <mach/hardware.h> +#include <mach/cpufreq.h> +#include <mach/common.h> + +#include "clock.h" + +struct davinci_cpufreq { + struct device *dev; + struct clk *armclk; +}; +static struct davinci_cpufreq cpufreq; + +static int davinci_verify_speed(struct cpufreq_policy *policy) +{ + struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; + struct cpufreq_frequency_table *freq_table = pdata->freq_table; + struct clk *armclk = cpufreq.armclk; + + if (freq_table) + return cpufreq_frequency_table_verify(policy, freq_table); + + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000; + policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000; + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + return 0; +} + +static unsigned int davinci_getspeed(unsigned int cpu) +{ + if (cpu) + return 0; + + return clk_get_rate(cpufreq.armclk) / 1000; +} + +static int davinci_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + int ret = 0; + unsigned int idx; + struct cpufreq_freqs freqs; + struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; + struct clk *armclk = cpufreq.armclk; + + /* + * Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. + */ + if (target_freq < policy->cpuinfo.min_freq) + target_freq = policy->cpuinfo.min_freq; + if (target_freq > policy->cpuinfo.max_freq) + target_freq = policy->cpuinfo.max_freq; + + freqs.old = davinci_getspeed(0); + freqs.new = clk_round_rate(armclk, target_freq * 1000) / 1000; + freqs.cpu = 0; + + if (freqs.old == freqs.new) + return ret; + + cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, + dev_driver_string(cpufreq.dev), + "transition: %u --> %u\n", freqs.old, freqs.new); + + ret = cpufreq_frequency_table_target(policy, pdata->freq_table, + freqs.new, relation, &idx); + if (ret) + return -EINVAL; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* if moving to higher frequency, up the voltage beforehand */ + if (pdata->set_voltage && freqs.new > freqs.old) + pdata->set_voltage(idx); + + ret = clk_set_rate(armclk, idx); + + /* if moving to lower freq, lower the voltage after lowering freq */ + if (pdata->set_voltage && freqs.new < freqs.old) + pdata->set_voltage(idx); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +static int __init davinci_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; + struct cpufreq_frequency_table *freq_table = pdata->freq_table; + + if (policy->cpu != 0) + return -EINVAL; + + /* Finish platform specific initialization */ + if (pdata->init) { + result = pdata->init(); + if (result) + return result; + } + + policy->cur = policy->min = policy->max = davinci_getspeed(0); + + if (freq_table) { + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!result) + cpufreq_frequency_table_get_attr(freq_table, + policy->cpu); + } else { + policy->cpuinfo.min_freq = policy->min; + policy->cpuinfo.max_freq = policy->max; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = davinci_getspeed(0); + + /* + * Time measurement across the target() function yields ~1500-1800us + * time taken with no drivers on notification list. + * Setting the latency to 2000 us to accomodate addition of drivers + * to pre/post change notification list. + */ + policy->cpuinfo.transition_latency = 2000 * 1000; + return 0; +} + +static int davinci_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static struct freq_attr *davinci_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver davinci_driver = { + .flags = CPUFREQ_STICKY, + .verify = davinci_verify_speed, + .target = davinci_target, + .get = davinci_getspeed, + .init = davinci_cpu_init, + .exit = davinci_cpu_exit, + .name = "davinci", + .attr = davinci_cpufreq_attr, +}; + +static int __init davinci_cpufreq_probe(struct platform_device *pdev) +{ + struct davinci_cpufreq_config *pdata = pdev->dev.platform_data; + + if (!pdata) + return -EINVAL; + if (!pdata->freq_table) + return -EINVAL; + + cpufreq.dev = &pdev->dev; + + cpufreq.armclk = clk_get(NULL, "arm"); + if (IS_ERR(cpufreq.armclk)) { + dev_err(cpufreq.dev, "Unable to get ARM clock\n"); + return PTR_ERR(cpufreq.armclk); + } + + return cpufreq_register_driver(&davinci_driver); +} + +static int __exit davinci_cpufreq_remove(struct platform_device *pdev) +{ + clk_put(cpufreq.armclk); + + return cpufreq_unregister_driver(&davinci_driver); +} + +static struct platform_driver davinci_cpufreq_driver = { + .driver = { + .name = "cpufreq-davinci", + .owner = THIS_MODULE, + }, + .remove = __exit_p(davinci_cpufreq_remove), +}; + +static int __init davinci_cpufreq_init(void) +{ + return platform_driver_probe(&davinci_cpufreq_driver, + davinci_cpufreq_probe); +} +late_initcall(davinci_cpufreq_init); + diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c new file mode 100644 index 000000000000..97a90f36fc92 --- /dev/null +++ b/arch/arm/mach-davinci/cpuidle.c @@ -0,0 +1,197 @@ +/* + * CPU idle for DaVinci SoCs + * + * Copyright (C) 2009 Texas Instruments Incorporated. http://www.ti.com/ + * + * Derived from Marvell Kirkwood CPU idle code + * (arch/arm/mach-kirkwood/cpuidle.c) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/cpuidle.h> +#include <linux/io.h> +#include <asm/proc-fns.h> + +#include <mach/cpuidle.h> + +#define DAVINCI_CPUIDLE_MAX_STATES 2 + +struct davinci_ops { + void (*enter) (u32 flags); + void (*exit) (u32 flags); + u32 flags; +}; + +/* fields in davinci_ops.flags */ +#define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) + +static struct cpuidle_driver davinci_idle_driver = { + .name = "cpuidle-davinci", + .owner = THIS_MODULE, +}; + +static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); +static void __iomem *ddr2_reg_base; + +#define DDR2_SDRCR_OFFSET 0xc +#define DDR2_SRPD_BIT BIT(23) +#define DDR2_LPMODEN_BIT BIT(31) + +static void davinci_save_ddr_power(int enter, bool pdown) +{ + u32 val; + + val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET); + + if (enter) { + if (pdown) + val |= DDR2_SRPD_BIT; + else + val &= ~DDR2_SRPD_BIT; + val |= DDR2_LPMODEN_BIT; + } else { + val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT); + } + + __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); +} + +static void davinci_c2state_enter(u32 flags) +{ + davinci_save_ddr_power(1, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN)); +} + +static void davinci_c2state_exit(u32 flags) +{ + davinci_save_ddr_power(0, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN)); +} + +static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { + [1] = { + .enter = davinci_c2state_enter, + .exit = davinci_c2state_exit, + }, +}; + +/* Actual code that puts the SoC in different idle states */ +static int davinci_enter_idle(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + struct davinci_ops *ops = cpuidle_get_statedata(state); + struct timeval before, after; + int idle_time; + + local_irq_disable(); + do_gettimeofday(&before); + + if (ops && ops->enter) + ops->enter(ops->flags); + /* Wait for interrupt state */ + cpu_do_idle(); + if (ops && ops->exit) + ops->exit(ops->flags); + + do_gettimeofday(&after); + local_irq_enable(); + idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + return idle_time; +} + +static int __init davinci_cpuidle_probe(struct platform_device *pdev) +{ + int ret; + struct cpuidle_device *device; + struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; + struct resource *ddr2_regs; + resource_size_t len; + + device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); + + if (!pdata) { + dev_err(&pdev->dev, "cannot get platform data\n"); + return -ENOENT; + } + + ddr2_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!ddr2_regs) { + dev_err(&pdev->dev, "cannot get DDR2 controller register base"); + return -ENODEV; + } + + len = resource_size(ddr2_regs); + + ddr2_regs = request_mem_region(ddr2_regs->start, len, ddr2_regs->name); + if (!ddr2_regs) + return -EBUSY; + + ddr2_reg_base = ioremap(ddr2_regs->start, len); + if (!ddr2_reg_base) { + ret = -ENOMEM; + goto ioremap_fail; + } + + ret = cpuidle_register_driver(&davinci_idle_driver); + if (ret) { + dev_err(&pdev->dev, "failed to register driver\n"); + goto driver_register_fail; + } + + /* Wait for interrupt state */ + device->states[0].enter = davinci_enter_idle; + device->states[0].exit_latency = 1; + device->states[0].target_residency = 10000; + device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(device->states[0].name, "WFI"); + strcpy(device->states[0].desc, "Wait for interrupt"); + + /* Wait for interrupt and DDR self refresh state */ + device->states[1].enter = davinci_enter_idle; + device->states[1].exit_latency = 10; + device->states[1].target_residency = 10000; + device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(device->states[1].name, "DDR SR"); + strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); + if (pdata->ddr2_pdown) + davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; + cpuidle_set_statedata(&device->states[1], &davinci_states[1]); + + device->state_count = DAVINCI_CPUIDLE_MAX_STATES; + + ret = cpuidle_register_device(device); + if (ret) { + dev_err(&pdev->dev, "failed to register device\n"); + goto device_register_fail; + } + + return 0; + +device_register_fail: + cpuidle_unregister_driver(&davinci_idle_driver); +driver_register_fail: + iounmap(ddr2_reg_base); +ioremap_fail: + release_mem_region(ddr2_regs->start, len); + return ret; +} + +static struct platform_driver davinci_cpuidle_driver = { + .driver = { + .name = "cpuidle-davinci", + .owner = THIS_MODULE, + }, +}; + +static int __init davinci_cpuidle_init(void) +{ + return platform_driver_probe(&davinci_cpuidle_driver, + davinci_cpuidle_probe); +} +device_initcall(davinci_cpuidle_init); + diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 19b2748357fc..b22b5cf04250 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -8,22 +8,17 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ -#include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> -#include <linux/platform_device.h> #include <asm/mach/map.h> -#include <mach/clock.h> #include <mach/psc.h> -#include <mach/mux.h> #include <mach/irqs.h> #include <mach/cputype.h> #include <mach/common.h> #include <mach/time.h> #include <mach/da8xx.h> -#include <mach/asp.h> #include "clock.h" #include "mux.h" @@ -193,14 +188,14 @@ static struct clk uart1_clk = { .name = "uart1", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_UART1, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk uart2_clk = { .name = "uart2", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_UART2, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk spi0_clk = { @@ -213,98 +208,98 @@ static struct clk spi1_clk = { .name = "spi1", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_SPI1, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk ecap0_clk = { .name = "ecap0", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_ECAP, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk ecap1_clk = { .name = "ecap1", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_ECAP, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk ecap2_clk = { .name = "ecap2", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_ECAP, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk pwm0_clk = { .name = "pwm0", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_PWM, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk pwm1_clk = { .name = "pwm1", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_PWM, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk pwm2_clk = { .name = "pwm2", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_PWM, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk eqep0_clk = { .name = "eqep0", .parent = &pll0_sysclk2, .lpsc = DA830_LPSC1_EQEP, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk eqep1_clk = { .name = "eqep1", .parent = &pll0_sysclk2, .lpsc = DA830_LPSC1_EQEP, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk lcdc_clk = { .name = "lcdc", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_LCDC, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk mcasp0_clk = { .name = "mcasp0", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_McASP0, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk mcasp1_clk = { .name = "mcasp1", .parent = &pll0_sysclk2, .lpsc = DA830_LPSC1_McASP1, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk mcasp2_clk = { .name = "mcasp2", .parent = &pll0_sysclk2, .lpsc = DA830_LPSC1_McASP2, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk usb20_clk = { .name = "usb20", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_USB20, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk aemif_clk = { @@ -332,36 +327,36 @@ static struct clk emac_clk = { .name = "emac", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_CPGMAC, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk gpio_clk = { .name = "gpio", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_GPIO, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk i2c1_clk = { .name = "i2c1", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_I2C, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk usb11_clk = { .name = "usb11", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_USB11, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk emif3_clk = { .name = "emif3", .parent = &pll0_sysclk5, .lpsc = DA8XX_LPSC1_EMIF3C, + .gpsc = 1, .flags = ALWAYS_ENABLED, - .psc_ctlr = 1, }; static struct clk arm_clk = { @@ -411,7 +406,7 @@ static struct davinci_clk da830_clks[] = { CLK(NULL, "pwm2", &pwm2_clk), CLK("eqep.0", NULL, &eqep0_clk), CLK("eqep.1", NULL, &eqep1_clk), - CLK("da830_lcdc", NULL, &lcdc_clk), + CLK("da8xx_lcdc.0", NULL, &lcdc_clk), CLK("davinci-mcasp.0", NULL, &mcasp0_clk), CLK("davinci-mcasp.1", NULL, &mcasp1_clk), CLK("davinci-mcasp.2", NULL, &mcasp2_clk), @@ -1143,7 +1138,21 @@ static struct davinci_id da830_ids[] = { .part_no = 0xb7df, .manufacturer = 0x017, /* 0x02f >> 1 */ .cpu_id = DAVINCI_CPU_ID_DA830, - .name = "da830/omap l137", + .name = "da830/omap-l137 rev1.0", + }, + { + .variant = 0x8, + .part_no = 0xb7df, + .manufacturer = 0x017, + .cpu_id = DAVINCI_CPU_ID_DA830, + .name = "da830/omap-l137 rev1.1", + }, + { + .variant = 0x9, + .part_no = 0xb7df, + .manufacturer = 0x017, + .cpu_id = DAVINCI_CPU_ID_DA830, + .name = "da830/omap-l137 rev2.0", }, }; @@ -1178,13 +1187,11 @@ static struct davinci_timer_info da830_timer_info = { static struct davinci_soc_info davinci_soc_info_da830 = { .io_desc = da830_io_desc, .io_desc_num = ARRAY_SIZE(da830_io_desc), - .jtag_id_base = IO_ADDRESS(DA8XX_JTAG_ID_REG), .ids = da830_ids, .ids_num = ARRAY_SIZE(da830_ids), .cpu_clks = da830_clks, .psc_bases = da830_psc_bases, .psc_bases_num = ARRAY_SIZE(da830_psc_bases), - .pinmux_base = IO_ADDRESS(DA8XX_BOOT_CFG_BASE + 0x120), .pinmux_pins = da830_pins, .pinmux_pins_num = ARRAY_SIZE(da830_pins), .intc_base = (void __iomem *)DA8XX_CP_INTC_VIRT, @@ -1201,5 +1208,13 @@ static struct davinci_soc_info davinci_soc_info_da830 = { void __init da830_init(void) { + da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K); + if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module")) + return; + + davinci_soc_info_da830.jtag_id_base = + DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG); + davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG_VIRT(0x120); + davinci_common_init(&davinci_soc_info_da830); } diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 192d719a47df..717806c6cef9 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -11,31 +11,41 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ -#include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/cpufreq.h> +#include <linux/regulator/consumer.h> #include <asm/mach/map.h> -#include <mach/clock.h> #include <mach/psc.h> -#include <mach/mux.h> #include <mach/irqs.h> #include <mach/cputype.h> #include <mach/common.h> #include <mach/time.h> #include <mach/da8xx.h> +#include <mach/cpufreq.h> #include "clock.h" #include "mux.h" +/* SoC specific clock flags */ +#define DA850_CLK_ASYNC3 BIT(16) + #define DA850_PLL1_BASE 0x01e1a000 #define DA850_TIMER64P2_BASE 0x01f0c000 #define DA850_TIMER64P3_BASE 0x01f0d000 #define DA850_REF_FREQ 24000000 +#define CFGCHIP3_ASYNC3_CLKSRC BIT(4) +#define CFGCHIP0_PLL_MASTER_LOCK BIT(4) + +static int da850_set_armrate(struct clk *clk, unsigned long rate); +static int da850_round_armrate(struct clk *clk, unsigned long rate); +static int da850_set_pll0rate(struct clk *clk, unsigned long armrate); + static struct pll_data pll0_data = { .num = 1, .phys_base = DA8XX_PLL0_BASE, @@ -52,6 +62,7 @@ static struct clk pll0_clk = { .parent = &ref_clk, .pll_data = &pll0_data, .flags = CLK_PLL, + .set_rate = da850_set_pll0rate, }; static struct clk pll0_aux_clk = { @@ -210,16 +221,16 @@ static struct clk tpcc1_clk = { .name = "tpcc1", .parent = &pll0_sysclk2, .lpsc = DA850_LPSC1_TPCC1, + .gpsc = 1, .flags = CLK_PSC | ALWAYS_ENABLED, - .psc_ctlr = 1, }; static struct clk tptc2_clk = { .name = "tptc2", .parent = &pll0_sysclk2, .lpsc = DA850_LPSC1_TPTC2, + .gpsc = 1, .flags = ALWAYS_ENABLED, - .psc_ctlr = 1, }; static struct clk uart0_clk = { @@ -232,14 +243,16 @@ static struct clk uart1_clk = { .name = "uart1", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_UART1, - .psc_ctlr = 1, + .gpsc = 1, + .flags = DA850_CLK_ASYNC3, }; static struct clk uart2_clk = { .name = "uart2", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_UART2, - .psc_ctlr = 1, + .gpsc = 1, + .flags = DA850_CLK_ASYNC3, }; static struct clk aintc_clk = { @@ -253,22 +266,22 @@ static struct clk gpio_clk = { .name = "gpio", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_GPIO, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk i2c1_clk = { .name = "i2c1", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_I2C, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk emif3_clk = { .name = "emif3", .parent = &pll0_sysclk5, .lpsc = DA8XX_LPSC1_EMIF3C, + .gpsc = 1, .flags = ALWAYS_ENABLED, - .psc_ctlr = 1, }; static struct clk arm_clk = { @@ -276,6 +289,8 @@ static struct clk arm_clk = { .parent = &pll0_sysclk6, .lpsc = DA8XX_LPSC0_ARM, .flags = ALWAYS_ENABLED, + .set_rate = da850_set_armrate, + .round_rate = da850_round_armrate, }; static struct clk rmii_clk = { @@ -287,21 +302,22 @@ static struct clk emac_clk = { .name = "emac", .parent = &pll0_sysclk4, .lpsc = DA8XX_LPSC1_CPGMAC, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk mcasp_clk = { .name = "mcasp", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_McASP0, - .psc_ctlr = 1, + .gpsc = 1, + .flags = DA850_CLK_ASYNC3, }; static struct clk lcdc_clk = { .name = "lcdc", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_LCDC, - .psc_ctlr = 1, + .gpsc = 1, }; static struct clk mmcsd_clk = { @@ -404,6 +420,14 @@ static const struct mux_config da850_pins[] = { MUX_CFG(DA850, MII_RXD_0, 3, 28, 15, 8, false) MUX_CFG(DA850, MDIO_CLK, 4, 0, 15, 8, false) MUX_CFG(DA850, MDIO_D, 4, 4, 15, 8, false) + MUX_CFG(DA850, RMII_TXD_0, 14, 12, 15, 8, false) + MUX_CFG(DA850, RMII_TXD_1, 14, 8, 15, 8, false) + MUX_CFG(DA850, RMII_TXEN, 14, 16, 15, 8, false) + MUX_CFG(DA850, RMII_CRS_DV, 15, 4, 15, 8, false) + MUX_CFG(DA850, RMII_RXD_0, 14, 24, 15, 8, false) + MUX_CFG(DA850, RMII_RXD_1, 14, 20, 15, 8, false) + MUX_CFG(DA850, RMII_RXER, 14, 28, 15, 8, false) + MUX_CFG(DA850, RMII_MHZ_50_CLK, 15, 0, 15, 0, false) /* McASP function */ MUX_CFG(DA850, ACLKR, 0, 0, 15, 1, false) MUX_CFG(DA850, ACLKX, 0, 4, 15, 1, false) @@ -506,8 +530,9 @@ static const struct mux_config da850_pins[] = { MUX_CFG(DA850, EMA_WAIT_1, 6, 24, 15, 1, false) MUX_CFG(DA850, NEMA_CS_2, 7, 0, 15, 1, false) /* GPIO function */ + MUX_CFG(DA850, GPIO2_6, 6, 4, 15, 8, false) + MUX_CFG(DA850, GPIO2_8, 5, 28, 15, 8, false) MUX_CFG(DA850, GPIO2_15, 5, 0, 15, 8, false) - MUX_CFG(DA850, GPIO8_10, 18, 28, 15, 8, false) MUX_CFG(DA850, GPIO4_0, 10, 28, 15, 8, false) MUX_CFG(DA850, GPIO4_1, 10, 24, 15, 8, false) #endif @@ -547,6 +572,14 @@ const short da850_cpgmac_pins[] __initdata = { -1 }; +const short da850_rmii_pins[] __initdata = { + DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, + DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, + DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, + DA850_MDIO_D, + -1 +}; + const short da850_mcasp_pins[] __initdata = { DA850_AHCLKX, DA850_ACLKX, DA850_AFSX, DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE, @@ -555,12 +588,11 @@ const short da850_mcasp_pins[] __initdata = { }; const short da850_lcdcntl_pins[] __initdata = { - DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3, DA850_LCD_D_4, - DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7, DA850_LCD_D_8, - DA850_LCD_D_9, DA850_LCD_D_10, DA850_LCD_D_11, DA850_LCD_D_12, - DA850_LCD_D_13, DA850_LCD_D_14, DA850_LCD_D_15, DA850_LCD_PCLK, - DA850_LCD_HSYNC, DA850_LCD_VSYNC, DA850_NLCD_AC_ENB_CS, DA850_GPIO2_15, - DA850_GPIO8_10, + DA850_LCD_D_0, DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3, + DA850_LCD_D_4, DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7, + DA850_LCD_D_8, DA850_LCD_D_9, DA850_LCD_D_10, DA850_LCD_D_11, + DA850_LCD_D_12, DA850_LCD_D_13, DA850_LCD_D_14, DA850_LCD_D_15, + DA850_LCD_PCLK, DA850_LCD_HSYNC, DA850_LCD_VSYNC, DA850_NLCD_AC_ENB_CS, -1 }; @@ -790,16 +822,221 @@ static struct davinci_timer_info da850_timer_info = { .clocksource_id = T0_TOP, }; +static void da850_set_async3_src(int pllnum) +{ + struct clk *clk, *newparent = pllnum ? &pll1_sysclk2 : &pll0_sysclk2; + struct davinci_clk *c; + unsigned int v; + int ret; + + for (c = da850_clks; c->lk.clk; c++) { + clk = c->lk.clk; + if (clk->flags & DA850_CLK_ASYNC3) { + ret = clk_set_parent(clk, newparent); + WARN(ret, "DA850: unable to re-parent clock %s", + clk->name); + } + } + + v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG)); + if (pllnum) + v |= CFGCHIP3_ASYNC3_CLKSRC; + else + v &= ~CFGCHIP3_ASYNC3_CLKSRC; + __raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG)); +} + +#ifdef CONFIG_CPU_FREQ +/* + * Notes: + * According to the TRM, minimum PLLM results in maximum power savings. + * The OPP definitions below should keep the PLLM as low as possible. + * + * The output of the PLLM must be between 400 to 600 MHz. + * This rules out prediv of anything but divide-by-one for 24Mhz OSC input. + */ +struct da850_opp { + unsigned int freq; /* in KHz */ + unsigned int prediv; + unsigned int mult; + unsigned int postdiv; + unsigned int cvdd_min; /* in uV */ + unsigned int cvdd_max; /* in uV */ +}; + +static const struct da850_opp da850_opp_300 = { + .freq = 300000, + .prediv = 1, + .mult = 25, + .postdiv = 2, + .cvdd_min = 1140000, + .cvdd_max = 1320000, +}; + +static const struct da850_opp da850_opp_200 = { + .freq = 200000, + .prediv = 1, + .mult = 25, + .postdiv = 3, + .cvdd_min = 1050000, + .cvdd_max = 1160000, +}; + +static const struct da850_opp da850_opp_96 = { + .freq = 96000, + .prediv = 1, + .mult = 20, + .postdiv = 5, + .cvdd_min = 950000, + .cvdd_max = 1050000, +}; + +#define OPP(freq) \ + { \ + .index = (unsigned int) &da850_opp_##freq, \ + .frequency = freq * 1000, \ + } + +static struct cpufreq_frequency_table da850_freq_table[] = { + OPP(300), + OPP(200), + OPP(96), + { + .index = 0, + .frequency = CPUFREQ_TABLE_END, + }, +}; + +#ifdef CONFIG_REGULATOR +static struct regulator *cvdd; + +static int da850_set_voltage(unsigned int index) +{ + struct da850_opp *opp; + + if (!cvdd) + return -ENODEV; + + opp = (struct da850_opp *) da850_freq_table[index].index; + + return regulator_set_voltage(cvdd, opp->cvdd_min, opp->cvdd_max); +} + +static int da850_regulator_init(void) +{ + cvdd = regulator_get(NULL, "cvdd"); + if (WARN(IS_ERR(cvdd), "Unable to obtain voltage regulator for CVDD;" + " voltage scaling unsupported\n")) { + return PTR_ERR(cvdd); + } + + return 0; +} +#endif + +static struct davinci_cpufreq_config cpufreq_info = { + .freq_table = &da850_freq_table[0], +#ifdef CONFIG_REGULATOR + .init = da850_regulator_init, + .set_voltage = da850_set_voltage, +#endif +}; + +static struct platform_device da850_cpufreq_device = { + .name = "cpufreq-davinci", + .dev = { + .platform_data = &cpufreq_info, + }, +}; + +int __init da850_register_cpufreq(void) +{ + return platform_device_register(&da850_cpufreq_device); +} + +static int da850_round_armrate(struct clk *clk, unsigned long rate) +{ + int i, ret = 0, diff; + unsigned int best = (unsigned int) -1; + + rate /= 1000; /* convert to kHz */ + + for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + diff = da850_freq_table[i].frequency - rate; + if (diff < 0) + diff = -diff; + + if (diff < best) { + best = diff; + ret = da850_freq_table[i].frequency; + } + } + + return ret * 1000; +} + +static int da850_set_armrate(struct clk *clk, unsigned long index) +{ + struct clk *pllclk = &pll0_clk; + + return clk_set_rate(pllclk, index); +} + +static int da850_set_pll0rate(struct clk *clk, unsigned long index) +{ + unsigned int prediv, mult, postdiv; + struct da850_opp *opp; + struct pll_data *pll = clk->pll_data; + unsigned int v; + int ret; + + opp = (struct da850_opp *) da850_freq_table[index].index; + prediv = opp->prediv; + mult = opp->mult; + postdiv = opp->postdiv; + + /* Unlock writing to PLL registers */ + v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG)); + v &= ~CFGCHIP0_PLL_MASTER_LOCK; + __raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG)); + + ret = davinci_set_pllrate(pll, prediv, mult, postdiv); + if (WARN_ON(ret)) + return ret; + + return 0; +} +#else +int __init da850_register_cpufreq(void) +{ + return 0; +} + +static int da850_set_armrate(struct clk *clk, unsigned long rate) +{ + return -EINVAL; +} + +static int da850_set_pll0rate(struct clk *clk, unsigned long armrate) +{ + return -EINVAL; +} + +static int da850_round_armrate(struct clk *clk, unsigned long rate) +{ + return clk->rate; +} +#endif + + static struct davinci_soc_info davinci_soc_info_da850 = { .io_desc = da850_io_desc, .io_desc_num = ARRAY_SIZE(da850_io_desc), - .jtag_id_base = IO_ADDRESS(DA8XX_JTAG_ID_REG), .ids = da850_ids, .ids_num = ARRAY_SIZE(da850_ids), .cpu_clks = da850_clks, .psc_bases = da850_psc_bases, .psc_bases_num = ARRAY_SIZE(da850_psc_bases), - .pinmux_base = IO_ADDRESS(DA8XX_BOOT_CFG_BASE + 0x120), .pinmux_pins = da850_pins, .pinmux_pins_num = ARRAY_SIZE(da850_pins), .intc_base = (void __iomem *)DA8XX_CP_INTC_VIRT, @@ -816,5 +1053,22 @@ static struct davinci_soc_info davinci_soc_info_da850 = { void __init da850_init(void) { + da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K); + if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module")) + return; + + davinci_soc_info_da850.jtag_id_base = + DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG); + davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG_VIRT(0x120); + davinci_common_init(&davinci_soc_info_da850); + + /* + * Move the clock source of Async3 domain to PLL1 SYSCLK2. + * This helps keeping the peripherals on this domain insulated + * from CPU frequency changes caused by DVFS. The firmware sets + * both PLL0 and PLL1 to the same frequency so, there should not + * be any noticible change even in non-DVFS use cases. + */ + da850_set_async3_src(1); } diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 58ad5b66fd60..dd2d32c4ce86 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -10,8 +10,6 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ -#include <linux/module.h> -#include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> @@ -21,7 +19,7 @@ #include <mach/common.h> #include <mach/time.h> #include <mach/da8xx.h> -#include <video/da8xx-fb.h> +#include <mach/cpuidle.h> #include "clock.h" @@ -30,6 +28,7 @@ #define DA8XX_TPTC1_BASE 0x01c08400 #define DA8XX_WDOG_BASE 0x01c21000 /* DA8XX_TIMER64P1_BASE */ #define DA8XX_I2C0_BASE 0x01c22000 +#define DA8XX_RTC_BASE 0x01C23000 #define DA8XX_EMAC_CPPI_PORT_BASE 0x01e20000 #define DA8XX_EMAC_CPGMACSS_BASE 0x01e22000 #define DA8XX_EMAC_CPGMAC_BASE 0x01e23000 @@ -43,6 +42,8 @@ #define DA8XX_MDIO_REG_OFFSET 0x4000 #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K +void __iomem *da8xx_syscfg_base; + static struct plat_serial8250_port da8xx_serial_pdata[] = { { .mapbase = DA8XX_UART0_BASE, @@ -282,6 +283,11 @@ static struct platform_device da8xx_emac_device = { .resource = da8xx_emac_resources, }; +int __init da8xx_register_emac(void) +{ + return platform_device_register(&da8xx_emac_device); +} + static struct resource da830_mcasp1_resources[] = { { .name = "mcasp1", @@ -338,12 +344,7 @@ static struct platform_device da850_mcasp_device = { .resource = da850_mcasp_resources, }; -int __init da8xx_register_emac(void) -{ - return platform_device_register(&da8xx_emac_device); -} - -void __init da8xx_init_mcasp(int id, struct snd_platform_data *pdata) +void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata) { /* DA830/OMAP-L137 has 3 instances of McASP */ if (cpu_is_davinci_da830() && id == 1) { @@ -379,10 +380,16 @@ static struct lcd_ctrl_config lcd_cfg = { .raster_order = 0, }; -static struct da8xx_lcdc_platform_data da850_evm_lcdc_pdata = { - .manu_name = "sharp", - .controller_data = &lcd_cfg, - .type = "Sharp_LK043T1DG01", +struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = { + .manu_name = "sharp", + .controller_data = &lcd_cfg, + .type = "Sharp_LCD035Q3DG01", +}; + +struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata = { + .manu_name = "sharp", + .controller_data = &lcd_cfg, + .type = "Sharp_LK043T1DG01", }; static struct resource da8xx_lcdc_resources[] = { @@ -398,19 +405,17 @@ static struct resource da8xx_lcdc_resources[] = { }, }; -static struct platform_device da850_lcdc_device = { +static struct platform_device da8xx_lcdc_device = { .name = "da8xx_lcdc", .id = 0, .num_resources = ARRAY_SIZE(da8xx_lcdc_resources), .resource = da8xx_lcdc_resources, - .dev = { - .platform_data = &da850_evm_lcdc_pdata, - } }; -int __init da8xx_register_lcdc(void) +int __init da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata) { - return platform_device_register(&da850_lcdc_device); + da8xx_lcdc_device.dev.platform_data = pdata; + return platform_device_register(&da8xx_lcdc_device); } static struct resource da8xx_mmcsd0_resources[] = { @@ -448,3 +453,66 @@ int __init da8xx_register_mmcsd0(struct davinci_mmc_config *config) da8xx_mmcsd0_device.dev.platform_data = config; return platform_device_register(&da8xx_mmcsd0_device); } + +static struct resource da8xx_rtc_resources[] = { + { + .start = DA8XX_RTC_BASE, + .end = DA8XX_RTC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { /* timer irq */ + .start = IRQ_DA8XX_RTC, + .end = IRQ_DA8XX_RTC, + .flags = IORESOURCE_IRQ, + }, + { /* alarm irq */ + .start = IRQ_DA8XX_RTC, + .end = IRQ_DA8XX_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device da8xx_rtc_device = { + .name = "omap_rtc", + .id = -1, + .num_resources = ARRAY_SIZE(da8xx_rtc_resources), + .resource = da8xx_rtc_resources, +}; + +int da8xx_register_rtc(void) +{ + /* Unlock the rtc's registers */ + __raw_writel(0x83e70b13, IO_ADDRESS(DA8XX_RTC_BASE + 0x6c)); + __raw_writel(0x95a4f1e0, IO_ADDRESS(DA8XX_RTC_BASE + 0x70)); + + return platform_device_register(&da8xx_rtc_device); +} + +static struct resource da8xx_cpuidle_resources[] = { + { + .start = DA8XX_DDR2_CTL_BASE, + .end = DA8XX_DDR2_CTL_BASE + SZ_32K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +/* DA8XX devices support DDR2 power down */ +static struct davinci_cpuidle_config da8xx_cpuidle_pdata = { + .ddr2_pdown = 1, +}; + + +static struct platform_device da8xx_cpuidle_device = { + .name = "cpuidle-davinci", + .num_resources = ARRAY_SIZE(da8xx_cpuidle_resources), + .resource = da8xx_cpuidle_resources, + .dev = { + .platform_data = &da8xx_cpuidle_pdata, + }, +}; + +int __init da8xx_register_cpuidle(void) +{ + return platform_device_register(&da8xx_cpuidle_device); +} + diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index a55b650db71e..147949650c25 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -9,15 +9,11 @@ * (at your option) any later version. */ -#include <linux/module.h> -#include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/io.h> -#include <asm/mach/map.h> - #include <mach/hardware.h> #include <mach/i2c.h> #include <mach/irqs.h> @@ -177,7 +173,7 @@ void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config) mmcsd1_resources[0].start = DM365_MMCSD1_BASE; mmcsd1_resources[0].end = DM365_MMCSD1_BASE + SZ_4K - 1; - mmcsd0_resources[2].start = IRQ_DM365_SDIOINT1; + mmcsd1_resources[2].start = IRQ_DM365_SDIOINT1; } else break; diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 059670018aff..dedf4d4f3a27 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -8,7 +8,6 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ -#include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/serial_8250.h> @@ -21,7 +20,6 @@ #include <asm/mach/map.h> #include <mach/dm355.h> -#include <mach/clock.h> #include <mach/cputype.h> #include <mach/edma.h> #include <mach/psc.h> diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index e81517434703..2ec619ec1657 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -12,7 +12,6 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/serial_8250.h> @@ -23,7 +22,6 @@ #include <asm/mach/map.h> #include <mach/dm365.h> -#include <mach/clock.h> #include <mach/cputype.h> #include <mach/edma.h> #include <mach/psc.h> @@ -32,6 +30,8 @@ #include <mach/time.h> #include <mach/serial.h> #include <mach/common.h> +#include <mach/asp.h> +#include <mach/keyscan.h> #include "clock.h" #include "mux.h" @@ -369,7 +369,7 @@ static struct clk timer3_clk = { static struct clk usb_clk = { .name = "usb", - .parent = &pll2_sysclk1, + .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_USB, }; @@ -456,7 +456,7 @@ static struct davinci_clk dm365_clks[] = { CLK(NULL, "usb", &usb_clk), CLK("davinci_emac.1", NULL, &emac_clk), CLK("voice_codec", NULL, &voicecodec_clk), - CLK("soc-audio.0", NULL, &asp0_clk), + CLK("davinci-asp.0", NULL, &asp0_clk), CLK(NULL, "rto", &rto_clk), CLK(NULL, "mjcp", &mjcp_clk), CLK(NULL, NULL, NULL), @@ -531,7 +531,7 @@ MUX_CFG(DM365, EMAC_CRS, 3, 2, 1, 1, false) MUX_CFG(DM365, EMAC_MDIO, 3, 1, 1, 1, false) MUX_CFG(DM365, EMAC_MDCLK, 3, 0, 1, 1, false) -MUX_CFG(DM365, KEYPAD, 2, 0, 0x3f, 0x3f, false) +MUX_CFG(DM365, KEYSCAN, 2, 0, 0x3f, 0x3f, false) MUX_CFG(DM365, PWM0, 1, 0, 3, 2, false) MUX_CFG(DM365, PWM0_G23, 3, 26, 3, 3, false) @@ -603,6 +603,9 @@ INT_CFG(DM365, INT_IMX1_ENABLE, 24, 1, 1, false) INT_CFG(DM365, INT_IMX1_DISABLE, 24, 1, 0, false) INT_CFG(DM365, INT_NSF_ENABLE, 25, 1, 1, false) INT_CFG(DM365, INT_NSF_DISABLE, 25, 1, 0, false) + +EVT_CFG(DM365, EVT2_ASP_TX, 0, 1, 0, false) +EVT_CFG(DM365, EVT3_ASP_RX, 1, 1, 0, false) #endif }; @@ -696,6 +699,7 @@ static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { [IRQ_I2C] = 3, [IRQ_UARTINT0] = 3, [IRQ_UARTINT1] = 3, + [IRQ_DM365_RTCINT] = 3, [IRQ_DM365_SPIINT0_0] = 3, [IRQ_DM365_SPIINT3_0] = 3, [IRQ_DM365_GPIO0] = 3, @@ -806,6 +810,50 @@ static struct platform_device dm365_edma_device = { .resource = edma_resources, }; +static struct resource dm365_asp_resources[] = { + { + .start = DAVINCI_DM365_ASP0_BASE, + .end = DAVINCI_DM365_ASP0_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = DAVINCI_DMA_ASP0_TX, + .end = DAVINCI_DMA_ASP0_TX, + .flags = IORESOURCE_DMA, + }, + { + .start = DAVINCI_DMA_ASP0_RX, + .end = DAVINCI_DMA_ASP0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +static struct platform_device dm365_asp_device = { + .name = "davinci-asp", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_asp_resources), + .resource = dm365_asp_resources, +}; + +static struct resource dm365_rtc_resources[] = { + { + .start = DM365_RTC_BASE, + .end = DM365_RTC_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_DM365_RTCINT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dm365_rtc_device = { + .name = "rtc_davinci", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_rtc_resources), + .resource = dm365_rtc_resources, +}; + static struct map_desc dm365_io_desc[] = { { .virtual = IO_VIRT, @@ -822,6 +870,28 @@ static struct map_desc dm365_io_desc[] = { }, }; +static struct resource dm365_ks_resources[] = { + { + /* registers */ + .start = DM365_KEYSCAN_BASE, + .end = DM365_KEYSCAN_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + /* interrupt */ + .start = IRQ_DM365_KEYINT, + .end = IRQ_DM365_KEYINT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dm365_ks_device = { + .name = "davinci_keyscan", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_ks_resources), + .resource = dm365_ks_resources, +}; + /* Contents of JTAG ID register used to identify exact cpu type */ static struct davinci_id dm365_ids[] = { { @@ -907,6 +977,33 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { .sram_len = SZ_32K, }; +void __init dm365_init_asp(struct snd_platform_data *pdata) +{ + davinci_cfg_reg(DM365_MCBSP0_BDX); + davinci_cfg_reg(DM365_MCBSP0_X); + davinci_cfg_reg(DM365_MCBSP0_BFSX); + davinci_cfg_reg(DM365_MCBSP0_BDR); + davinci_cfg_reg(DM365_MCBSP0_R); + davinci_cfg_reg(DM365_MCBSP0_BFSR); + davinci_cfg_reg(DM365_EVT2_ASP_TX); + davinci_cfg_reg(DM365_EVT3_ASP_RX); + dm365_asp_device.dev.platform_data = pdata; + platform_device_register(&dm365_asp_device); +} + +void __init dm365_init_ks(struct davinci_ks_platform_data *pdata) +{ + davinci_cfg_reg(DM365_KEYSCAN); + dm365_ks_device.dev.platform_data = pdata; + platform_device_register(&dm365_ks_device); +} + +void __init dm365_init_rtc(void) +{ + davinci_cfg_reg(DM365_INT_PRTCSS); + platform_device_register(&dm365_rtc_device); +} + void __init dm365_init(void) { davinci_common_init(&davinci_soc_info_dm365); diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index d6e0fa5a8d8a..2cd008156dea 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -8,7 +8,6 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ -#include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/serial_8250.h> @@ -18,7 +17,6 @@ #include <asm/mach/map.h> #include <mach/dm644x.h> -#include <mach/clock.h> #include <mach/cputype.h> #include <mach/edma.h> #include <mach/irqs.h> @@ -370,6 +368,11 @@ MUX_CFG(DM644X, ATAEN_DISABLE, 0, 17, 1, 0, true) MUX_CFG(DM644X, HPIEN_DISABLE, 0, 29, 1, 0, true) MUX_CFG(DM644X, AEAW, 0, 0, 31, 31, true) +MUX_CFG(DM644X, AEAW0, 0, 0, 1, 0, true) +MUX_CFG(DM644X, AEAW1, 0, 1, 1, 0, true) +MUX_CFG(DM644X, AEAW2, 0, 2, 1, 0, true) +MUX_CFG(DM644X, AEAW3, 0, 3, 1, 0, true) +MUX_CFG(DM644X, AEAW4, 0, 4, 1, 0, true) MUX_CFG(DM644X, MSTK, 1, 9, 1, 0, false) diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 0976049c7b3b..829a44bcf799 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -8,7 +8,6 @@ * is licensed "as is" without any warranty of any kind, whether express * or implied. */ -#include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/serial_8250.h> @@ -18,7 +17,6 @@ #include <asm/mach/map.h> #include <mach/dm646x.h> -#include <mach/clock.h> #include <mach/cputype.h> #include <mach/edma.h> #include <mach/irqs.h> @@ -789,7 +787,14 @@ static struct davinci_id dm646x_ids[] = { .part_no = 0xb770, .manufacturer = 0x017, .cpu_id = DAVINCI_CPU_ID_DM6467, - .name = "dm6467", + .name = "dm6467_rev1.x", + }, + { + .variant = 0x1, + .part_no = 0xb770, + .manufacturer = 0x017, + .cpu_id = DAVINCI_CPU_ID_DM6467, + .name = "dm6467_rev3.x", }, }; diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index f2e57d272958..648fbb760ae1 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -18,22 +18,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/compiler.h> #include <linux/io.h> -#include <mach/cputype.h> -#include <mach/memory.h> -#include <mach/hardware.h> -#include <mach/irqs.h> #include <mach/edma.h> -#include <mach/mux.h> - /* Offsets matching "struct edmacc_param" */ #define PARM_OPT 0x00 @@ -509,43 +500,59 @@ static irqreturn_t dma_tc1err_handler(int irq, void *data) return IRQ_HANDLED; } -static int reserve_contiguous_params(int ctlr, unsigned int id, - unsigned int num_params, - unsigned int start_param) +static int reserve_contiguous_slots(int ctlr, unsigned int id, + unsigned int num_slots, + unsigned int start_slot) { int i, j; - unsigned int count = num_params; + unsigned int count = num_slots; + int stop_slot = start_slot; + DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY); - for (i = start_param; i < edma_info[ctlr]->num_slots; ++i) { + for (i = start_slot; i < edma_info[ctlr]->num_slots; ++i) { j = EDMA_CHAN_SLOT(i); - if (!test_and_set_bit(j, edma_info[ctlr]->edma_inuse)) + if (!test_and_set_bit(j, edma_info[ctlr]->edma_inuse)) { + /* Record our current beginning slot */ + if (count == num_slots) + stop_slot = i; + count--; + set_bit(j, tmp_inuse); + if (count == 0) break; - else if (id == EDMA_CONT_PARAMS_FIXED_EXACT) - break; - else - count = num_params; + } else { + clear_bit(j, tmp_inuse); + + if (id == EDMA_CONT_PARAMS_FIXED_EXACT) { + stop_slot = i; + break; + } else + count = num_slots; + } } /* * We have to clear any bits that we set - * if we run out parameter RAMs, i.e we do find a set - * of contiguous parameter RAMs but do not find the exact number - * requested as we may reach the total number of parameter RAMs + * if we run out parameter RAM slots, i.e we do find a set + * of contiguous parameter RAM slots but do not find the exact number + * requested as we may reach the total number of parameter RAM slots */ - if (count) { - for (j = i - num_params + count + 1; j <= i ; ++j) + if (i == edma_info[ctlr]->num_slots) + stop_slot = i; + + for (j = start_slot; j < stop_slot; j++) + if (test_bit(j, tmp_inuse)) clear_bit(j, edma_info[ctlr]->edma_inuse); + if (count) return -EBUSY; - } - for (j = i - num_params + 1; j <= i; ++j) + for (j = i - num_slots + 1; j <= i; ++j) memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j), &dummy_paramset, PARM_SIZE); - return EDMA_CTLR_CHAN(ctlr, i - num_params + 1); + return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1); } /*-----------------------------------------------------------------------*/ @@ -743,26 +750,27 @@ EXPORT_SYMBOL(edma_free_slot); /** * edma_alloc_cont_slots- alloc contiguous parameter RAM slots * The API will return the starting point of a set of - * contiguous PARAM's that have been requested + * contiguous parameter RAM slots that have been requested * * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT - * @count: number of contiguous Paramter RAM's - * @param - the start value of Parameter RAM that should be passed if id + * @count: number of contiguous Paramter RAM slots + * @slot - the start value of Parameter RAM slot that should be passed if id * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT * * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of - * contiguous Parameter RAMs from parameter RAM 64 in the case of DaVinci SOCs - * and 32 in the case of Primus + * contiguous Parameter RAM slots from parameter RAM 64 in the case of + * DaVinci SOCs and 32 in the case of DA8xx SOCs. * * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a - * set of contiguous parameter RAMs from the "param" that is passed as an + * set of contiguous parameter RAM slots from the "slot" that is passed as an * argument to the API. * * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries - * starts looking for a set of contiguous parameter RAMs from the "param" + * starts looking for a set of contiguous parameter RAMs from the "slot" * that is passed as an argument to the API. On failure the API will try to - * find a set of contiguous Parameter RAMs in the remaining Parameter RAMs + * find a set of contiguous Parameter RAM slots from the remaining Parameter + * RAM slots */ int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) { @@ -771,12 +779,13 @@ int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) * the number of channels and lesser than the total number * of slots */ - if (slot < edma_info[ctlr]->num_channels || - slot >= edma_info[ctlr]->num_slots) + if ((id != EDMA_CONT_PARAMS_ANY) && + (slot < edma_info[ctlr]->num_channels || + slot >= edma_info[ctlr]->num_slots)) return -EINVAL; /* - * The number of parameter RAMs requested cannot be less than 1 + * The number of parameter RAM slots requested cannot be less than 1 * and cannot be more than the number of slots minus the number of * channels */ @@ -786,11 +795,11 @@ int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) switch (id) { case EDMA_CONT_PARAMS_ANY: - return reserve_contiguous_params(ctlr, id, count, + return reserve_contiguous_slots(ctlr, id, count, edma_info[ctlr]->num_channels); case EDMA_CONT_PARAMS_FIXED_EXACT: case EDMA_CONT_PARAMS_FIXED_NOT_EXACT: - return reserve_contiguous_params(ctlr, id, count, slot); + return reserve_contiguous_slots(ctlr, id, count, slot); default: return -EINVAL; } @@ -799,21 +808,21 @@ int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) EXPORT_SYMBOL(edma_alloc_cont_slots); /** - * edma_free_cont_slots - deallocate DMA parameter RAMs - * @slot: first parameter RAM of a set of parameter RAMs to be freed - * @count: the number of contiguous parameter RAMs to be freed + * edma_free_cont_slots - deallocate DMA parameter RAM slots + * @slot: first parameter RAM of a set of parameter RAM slots to be freed + * @count: the number of contiguous parameter RAM slots to be freed * * This deallocates the parameter RAM slots allocated by * edma_alloc_cont_slots. * Callers/applications need to keep track of sets of contiguous - * parameter RAMs that have been allocated using the edma_alloc_cont_slots + * parameter RAM slots that have been allocated using the edma_alloc_cont_slots * API. * Callers are responsible for ensuring the slots are inactive, and will * not be activated. */ int edma_free_cont_slots(unsigned slot, int count) { - unsigned ctlr; + unsigned ctlr, slot_to_free; int i; ctlr = EDMA_CTLR(slot); @@ -826,11 +835,11 @@ int edma_free_cont_slots(unsigned slot, int count) for (i = slot; i < slot + count; ++i) { ctlr = EDMA_CTLR(i); - slot = EDMA_CHAN_SLOT(i); + slot_to_free = EDMA_CHAN_SLOT(i); - memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), + memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free), &dummy_paramset, PARM_SIZE); - clear_bit(slot, edma_info[ctlr]->edma_inuse); + clear_bit(slot_to_free, edma_info[ctlr]->edma_inuse); } return 0; diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index f6ea9db11f41..744755b53236 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -12,23 +12,14 @@ #include <linux/errno.h> #include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/irq.h> -#include <linux/bitops.h> -#include <mach/cputype.h> -#include <mach/irqs.h> -#include <mach/hardware.h> -#include <mach/common.h> #include <mach/gpio.h> #include <asm/mach/irq.h> - static DEFINE_SPINLOCK(gpio_lock); struct davinci_gpio { diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h index e07f70ed7c53..834725f1e81d 100644 --- a/arch/arm/mach-davinci/include/mach/asp.h +++ b/arch/arm/mach-davinci/include/mach/asp.h @@ -11,6 +11,9 @@ #define DAVINCI_ASP0_BASE 0x01E02000 #define DAVINCI_ASP1_BASE 0x01E04000 +/* Bases of dm365 register banks */ +#define DAVINCI_DM365_ASP0_BASE 0x01D02000 + /* Bases of dm646x register banks */ #define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 #define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 1fd3917cae4e..6ca2c9a0a482 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -20,12 +20,6 @@ extern void davinci_irq_init(void); extern void __iomem *davinci_intc_base; extern int davinci_intc_type; -/* parameters describe VBUS sourcing for host mode */ -extern void setup_usb(unsigned mA, unsigned potpgt_msec); - -/* parameters describe VBUS sourcing for host mode */ -extern void setup_usb(unsigned mA, unsigned potpgt_msec); - struct davinci_timer_instance { void __iomem *base; u32 bottom_irq; diff --git a/arch/arm/mach-davinci/include/mach/cpufreq.h b/arch/arm/mach-davinci/include/mach/cpufreq.h new file mode 100644 index 000000000000..3c089cfb6cd6 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/cpufreq.h @@ -0,0 +1,26 @@ +/* + * TI DaVinci CPUFreq platform support. + * + * Copyright (C) 2009 Texas Instruments, Inc. http://www.ti.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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _MACH_DAVINCI_CPUFREQ_H +#define _MACH_DAVINCI_CPUFREQ_H + +#include <linux/cpufreq.h> + +struct davinci_cpufreq_config { + struct cpufreq_frequency_table *freq_table; + int (*set_voltage) (unsigned int index); + int (*init) (void); +}; + +#endif diff --git a/arch/arm/mach-davinci/include/mach/cpuidle.h b/arch/arm/mach-davinci/include/mach/cpuidle.h new file mode 100644 index 000000000000..cbfc6a9c81b4 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/cpuidle.h @@ -0,0 +1,17 @@ +/* + * TI DaVinci cpuidle platform support + * + * 2009 (C) Texas Instruments, Inc. http://www.ti.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. + */ +#ifndef _MACH_DAVINCI_CPUIDLE_H +#define _MACH_DAVINCI_CPUIDLE_H + +struct davinci_cpuidle_config { + u32 ddr2_pdown; +}; + +#endif diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index d4095d0572c6..90704910d343 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -11,12 +11,17 @@ #ifndef __ASM_ARCH_DAVINCI_DA8XX_H #define __ASM_ARCH_DAVINCI_DA8XX_H +#include <video/da8xx-fb.h> + #include <mach/serial.h> #include <mach/edma.h> #include <mach/i2c.h> #include <mach/emac.h> #include <mach/asp.h> #include <mach/mmc.h> +#include <mach/usb.h> + +extern void __iomem *da8xx_syscfg_base; /* * The cp_intc interrupt controller for the da8xx isn't in the same @@ -29,11 +34,15 @@ #define DA8XX_CP_INTC_SIZE SZ_8K #define DA8XX_CP_INTC_VIRT (IO_VIRT - DA8XX_CP_INTC_SIZE - SZ_4K) -#define DA8XX_BOOT_CFG_BASE (IO_PHYS + 0x14000) +#define DA8XX_SYSCFG_BASE (IO_PHYS + 0x14000) +#define DA8XX_SYSCFG_VIRT(x) (da8xx_syscfg_base + (x)) +#define DA8XX_JTAG_ID_REG 0x18 +#define DA8XX_CFGCHIP0_REG 0x17c +#define DA8XX_CFGCHIP2_REG 0x184 +#define DA8XX_CFGCHIP3_REG 0x188 #define DA8XX_PSC0_BASE 0x01c10000 #define DA8XX_PLL0_BASE 0x01c11000 -#define DA8XX_JTAG_ID_REG 0x01c14018 #define DA8XX_TIMER64P0_BASE 0x01c20000 #define DA8XX_TIMER64P1_BASE 0x01c21000 #define DA8XX_GPIO_BASE 0x01e26000 @@ -43,6 +52,7 @@ #define DA8XX_AEMIF_CS2_BASE 0x60000000 #define DA8XX_AEMIF_CS3_BASE 0x62000000 #define DA8XX_AEMIF_CTL_BASE 0x68000000 +#define DA8XX_DDR2_CTL_BASE 0xb0000000 #define PINMUX0 0x00 #define PINMUX1 0x04 @@ -71,13 +81,20 @@ void __init da850_init(void); int da8xx_register_edma(void); int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata); int da8xx_register_watchdog(void); +int da8xx_register_usb20(unsigned mA, unsigned potpgt); +int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata); int da8xx_register_emac(void); -int da8xx_register_lcdc(void); +int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata); int da8xx_register_mmcsd0(struct davinci_mmc_config *config); -void __init da8xx_init_mcasp(int id, struct snd_platform_data *pdata); +void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata); +int da8xx_register_rtc(void); +int da850_register_cpufreq(void); +int da8xx_register_cpuidle(void); extern struct platform_device da8xx_serial_device; extern struct emac_platform_data da8xx_emac_pdata; +extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata; +extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata; extern const short da830_emif25_pins[]; extern const short da830_spi0_pins[]; @@ -110,6 +127,7 @@ extern const short da850_uart2_pins[]; extern const short da850_i2c0_pins[]; extern const short da850_i2c1_pins[]; extern const short da850_cpgmac_pins[]; +extern const short da850_rmii_pins[]; extern const short da850_mcasp_pins[]; extern const short da850_lcdcntl_pins[]; extern const short da850_mmcsd0_pins[]; diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index 09db4343bb4c..f1710a30e7ba 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -16,6 +16,8 @@ #include <linux/platform_device.h> #include <mach/hardware.h> #include <mach/emac.h> +#include <mach/asp.h> +#include <mach/keyscan.h> #define DM365_EMAC_BASE (0x01D07000) #define DM365_EMAC_CNTRL_OFFSET (0x0000) @@ -24,6 +26,14 @@ #define DM365_EMAC_MDIO_OFFSET (0x4000) #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) +/* Base of key scan register bank */ +#define DM365_KEYSCAN_BASE (0x01C69400) + +#define DM365_RTC_BASE (0x01C69000) + void __init dm365_init(void); +void __init dm365_init_asp(struct snd_platform_data *pdata); +void __init dm365_init_ks(struct davinci_ks_platform_data *pdata); +void __init dm365_init_rtc(void); #endif /* __ASM_ARCH_DM365_H */ diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 0efb73852c2c..44e8f0fae9ea 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -22,7 +22,6 @@ #ifndef __ASM_ARCH_DM644X_H #define __ASM_ARCH_DM644X_H -#include <linux/platform_device.h> #include <mach/hardware.h> #include <mach/emac.h> #include <mach/asp.h> diff --git a/arch/arm/mach-davinci/include/mach/irqs.h b/arch/arm/mach-davinci/include/mach/irqs.h index 3c918a772619..354af71798dc 100644 --- a/arch/arm/mach-davinci/include/mach/irqs.h +++ b/arch/arm/mach-davinci/include/mach/irqs.h @@ -217,6 +217,7 @@ #define IRQ_DM365_SDIOINT0 23 #define IRQ_DM365_MMCINT1 27 #define IRQ_DM365_PWMINT3 28 +#define IRQ_DM365_RTCINT 29 #define IRQ_DM365_SDIOINT1 31 #define IRQ_DM365_SPIINT0_0 42 #define IRQ_DM365_SPIINT3_0 43 diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index bb84893a4e83..b60c693985ff 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -40,6 +40,11 @@ enum davinci_dm644x_index { /* AEAW functions */ DM644X_AEAW, + DM644X_AEAW0, + DM644X_AEAW1, + DM644X_AEAW2, + DM644X_AEAW3, + DM644X_AEAW4, /* Memory Stick */ DM644X_MSTK, @@ -237,8 +242,8 @@ enum davinci_dm365_index { DM365_EMAC_MDIO, DM365_EMAC_MDCLK, - /* Keypad */ - DM365_KEYPAD, + /* Key Scan */ + DM365_KEYSCAN, /* PWM */ DM365_PWM0, @@ -774,6 +779,14 @@ enum davinci_da850_index { DA850_MII_RXD_0, DA850_MDIO_CLK, DA850_MDIO_D, + DA850_RMII_TXD_0, + DA850_RMII_TXD_1, + DA850_RMII_TXEN, + DA850_RMII_CRS_DV, + DA850_RMII_RXD_0, + DA850_RMII_RXD_1, + DA850_RMII_RXER, + DA850_RMII_MHZ_50_CLK, /* McASP function */ DA850_ACLKR, @@ -881,8 +894,9 @@ enum davinci_da850_index { DA850_NEMA_CS_2, /* GPIO function */ + DA850_GPIO2_6, + DA850_GPIO2_8, DA850_GPIO2_15, - DA850_GPIO8_10, DA850_GPIO4_0, DA850_GPIO4_1, }; diff --git a/arch/arm/mach-davinci/include/mach/system.h b/arch/arm/mach-davinci/include/mach/system.h index 8e4f10fe1263..5a7d7581b8ce 100644 --- a/arch/arm/mach-davinci/include/mach/system.h +++ b/arch/arm/mach-davinci/include/mach/system.h @@ -11,9 +11,6 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H -#include <linux/io.h> -#include <mach/hardware.h> - extern void davinci_watchdog_reset(void); static inline void arch_idle(void) diff --git a/arch/arm/mach-davinci/include/mach/usb.h b/arch/arm/mach-davinci/include/mach/usb.h new file mode 100644 index 000000000000..e0bc4abe69c2 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/usb.h @@ -0,0 +1,59 @@ +/* + * USB related definitions + * + * Copyright (C) 2009 MontaVista Software, Inc. <source@mvista.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. + */ + +#ifndef __ASM_ARCH_USB_H +#define __ASM_ARCH_USB_H + +/* DA8xx CFGCHIP2 (USB 2.0 PHY Control) register bits */ +#define CFGCHIP2_PHYCLKGD (1 << 17) +#define CFGCHIP2_VBUSSENSE (1 << 16) +#define CFGCHIP2_RESET (1 << 15) +#define CFGCHIP2_OTGMODE (3 << 13) +#define CFGCHIP2_NO_OVERRIDE (0 << 13) +#define CFGCHIP2_FORCE_HOST (1 << 13) +#define CFGCHIP2_FORCE_DEVICE (2 << 13) +#define CFGCHIP2_FORCE_HOST_VBUS_LOW (3 << 13) +#define CFGCHIP2_USB1PHYCLKMUX (1 << 12) +#define CFGCHIP2_USB2PHYCLKMUX (1 << 11) +#define CFGCHIP2_PHYPWRDN (1 << 10) +#define CFGCHIP2_OTGPWRDN (1 << 9) +#define CFGCHIP2_DATPOL (1 << 8) +#define CFGCHIP2_USB1SUSPENDM (1 << 7) +#define CFGCHIP2_PHY_PLLON (1 << 6) /* override PLL suspend */ +#define CFGCHIP2_SESENDEN (1 << 5) /* Vsess_end comparator */ +#define CFGCHIP2_VBDTCTEN (1 << 4) /* Vbus comparator */ +#define CFGCHIP2_REFFREQ (0xf << 0) +#define CFGCHIP2_REFFREQ_12MHZ (1 << 0) +#define CFGCHIP2_REFFREQ_24MHZ (2 << 0) +#define CFGCHIP2_REFFREQ_48MHZ (3 << 0) + +struct da8xx_ohci_root_hub; + +typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_root_hub *hub, + unsigned port); + +/* Passed as the platform data to the OHCI driver */ +struct da8xx_ohci_root_hub { + /* Switch the port power on/off */ + int (*set_power)(unsigned port, int on); + /* Read the port power status */ + int (*get_power)(unsigned port); + /* Read the port over-current indicator */ + int (*get_oci)(unsigned port); + /* Over-current indicator change notification (pass NULL to disable) */ + int (*ocic_notify)(da8xx_ocic_handler_t handler); + + /* Time from power on to power good (in 2 ms units) */ + u8 potpgt; +}; + +void davinci_setup_usb(unsigned mA, unsigned potpgt_ms); + +#endif /* ifndef __ASM_ARCH_USB_H */ diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c index 898905e48946..f757e83415f3 100644 --- a/arch/arm/mach-davinci/mux.c +++ b/arch/arm/mach-davinci/mux.c @@ -19,7 +19,6 @@ #include <linux/module.h> #include <linux/spinlock.h> -#include <mach/hardware.h> #include <mach/mux.h> #include <mach/common.h> diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index a78b657e916e..04a3cb72c5ab 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -19,14 +19,11 @@ * */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> #include <linux/io.h> #include <mach/cputype.h> -#include <mach/hardware.h> #include <mach/psc.h> -#include <mach/mux.h> /* PSC register offsets */ #define EPCPR 0x070 diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index c530c7333d0a..7ce5ba086575 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c @@ -28,14 +28,8 @@ #include <linux/clk.h> #include <linux/io.h> -#include <asm/irq.h> -#include <mach/hardware.h> #include <mach/serial.h> -#include <mach/irqs.h> #include <mach/cputype.h> -#include <mach/common.h> - -#include "clock.h" static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, int offset) diff --git a/arch/arm/mach-davinci/sram.c b/arch/arm/mach-davinci/sram.c index 4f1fc9b318b3..db0f7787faf1 100644 --- a/arch/arm/mach-davinci/sram.c +++ b/arch/arm/mach-davinci/sram.c @@ -9,15 +9,12 @@ * (at your option) any later version. */ #include <linux/module.h> -#include <linux/kernel.h> #include <linux/init.h> #include <linux/genalloc.h> #include <mach/common.h> -#include <mach/memory.h> #include <mach/sram.h> - static struct gen_pool *sram_pool; void *sram_alloc(size_t len, dma_addr_t *dma) diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 0d1b6d407b46..42d985beece5 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -14,20 +14,14 @@ #include <linux/interrupt.h> #include <linux/clocksource.h> #include <linux/clockchips.h> -#include <linux/spinlock.h> #include <linux/io.h> #include <linux/clk.h> #include <linux/err.h> -#include <linux/device.h> #include <linux/platform_device.h> #include <mach/hardware.h> -#include <asm/system.h> -#include <asm/irq.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> -#include <asm/errno.h> -#include <mach/io.h> #include <mach/cputype.h> #include <mach/time.h> #include "clock.h" diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index 06f55931620c..31f0cbea0caa 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -1,21 +1,21 @@ /* * USB */ -#include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/usb/musb.h> -#include <linux/usb/otg.h> #include <mach/common.h> -#include <mach/hardware.h> #include <mach/irqs.h> #include <mach/cputype.h> +#include <mach/usb.h> -#define DAVINCI_USB_OTG_BASE 0x01C64000 +#define DAVINCI_USB_OTG_BASE 0x01c64000 + +#define DA8XX_USB0_BASE 0x01e00000 +#define DA8XX_USB1_BASE 0x01e25000 #if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) static struct musb_hdrc_eps_bits musb_eps[] = { @@ -85,10 +85,10 @@ static struct platform_device usb_dev = { .num_resources = ARRAY_SIZE(usb_resources), }; -void __init setup_usb(unsigned mA, unsigned potpgt_msec) +void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms) { - usb_data.power = mA / 2; - usb_data.potpgt = potpgt_msec / 2; + usb_data.power = mA > 510 ? 255 : mA / 2; + usb_data.potpgt = (potpgt_ms + 1) / 2; if (cpu_is_davinci_dm646x()) { /* Override the defaults as DM6467 uses different IRQs. */ @@ -100,11 +100,77 @@ void __init setup_usb(unsigned mA, unsigned potpgt_msec) platform_device_register(&usb_dev); } +#ifdef CONFIG_ARCH_DAVINCI_DA8XX +static struct resource da8xx_usb20_resources[] = { + { + .start = DA8XX_USB0_BASE, + .end = DA8XX_USB0_BASE + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_DA8XX_USB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +int __init da8xx_register_usb20(unsigned mA, unsigned potpgt) +{ + usb_data.clock = "usb20"; + usb_data.power = mA > 510 ? 255 : mA / 2; + usb_data.potpgt = (potpgt + 1) / 2; + + usb_dev.resource = da8xx_usb20_resources; + usb_dev.num_resources = ARRAY_SIZE(da8xx_usb20_resources); + + return platform_device_register(&usb_dev); +} +#endif /* CONFIG_DAVINCI_DA8XX */ + #else -void __init setup_usb(unsigned mA, unsigned potpgt_msec) +void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms) { } +#ifdef CONFIG_ARCH_DAVINCI_DA8XX +int __init da8xx_register_usb20(unsigned mA, unsigned potpgt) +{ + return 0; +} +#endif + #endif /* CONFIG_USB_MUSB_HDRC */ +#ifdef CONFIG_ARCH_DAVINCI_DA8XX +static struct resource da8xx_usb11_resources[] = { + [0] = { + .start = DA8XX_USB1_BASE, + .end = DA8XX_USB1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_DA8XX_IRQN, + .end = IRQ_DA8XX_IRQN, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device da8xx_usb11_device = { + .name = "ohci", + .id = 0, + .dev = { + .dma_mask = &da8xx_usb11_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(da8xx_usb11_resources), + .resource = da8xx_usb11_resources, +}; + +int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata) +{ + da8xx_usb11_device.dev.platform_data = pdata; + return platform_device_register(&da8xx_usb11_device); +} +#endif /* CONFIG_DAVINCI_DA8XX */ diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 5cc7e2e9e415..45876427eb2d 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -215,22 +215,18 @@ copy_thread(unsigned long clone_flags, /* * sys_execve() executes a new program. */ - asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp) { int error; char *filename; struct pt_regs *regs = (struct pt_regs *)((&name) + 6); - lock_kernel(); filename = getname(name); error = PTR_ERR(filename); if (IS_ERR(filename)) - goto out; + return error; error = do_execve(filename, argv, envp, regs); putname(filename); - out: - unlock_kernel(); return error; } diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 904255938216..21d0fd19276d 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -255,15 +255,12 @@ asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __ int error; char * filename; - lock_kernel(); filename = getname(name); error = PTR_ERR(filename); if (IS_ERR(filename)) - goto out; + return error; error = do_execve(filename, argv, envp, __frame); putname(filename); - out: - unlock_kernel(); return error; } diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index e2f33d0f9969..bd883faa983d 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -218,15 +218,12 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...) char * filename; struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); - lock_kernel(); filename = getname(name); error = PTR_ERR(filename); if (IS_ERR(filename)) - goto out; + return error; error = do_execve(filename, argv, envp, regs); putname(filename); -out: - unlock_kernel(); return error; } diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 4990495d7531..a35c661e5e89 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -473,7 +473,7 @@ void update_vsyscall_tz(void) { } -void update_vsyscall(struct timespec *wall, struct clocksource *c) +void update_vsyscall(struct timespec *wall, struct clocksource *c, u32 mult) { unsigned long flags; @@ -481,7 +481,7 @@ void update_vsyscall(struct timespec *wall, struct clocksource *c) /* copy fsyscall clock data */ fsyscall_gtod_data.clk_mask = c->mask; - fsyscall_gtod_data.clk_mult = c->mult; + fsyscall_gtod_data.clk_mult = mult; fsyscall_gtod_data.clk_shift = c->shift; fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio; fsyscall_gtod_data.clk_cycle_last = c->cycle_last; diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 8f8f4abab2ff..5c9ecd427090 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -352,15 +352,12 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp) char * filename; struct pt_regs *regs = (struct pt_regs *) &name; - lock_kernel(); filename = getname(name); error = PTR_ERR(filename); if (IS_ERR(filename)) - goto out; + return error; error = do_execve(filename, argv, envp, regs); putname(filename); -out: - unlock_kernel(); return error; } diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index df6a430de5eb..c7f1bfef1574 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h @@ -84,8 +84,16 @@ static inline int init_mips_clocksource(void) #endif } -extern void clocksource_set_clock(struct clocksource *cs, unsigned int clock); -extern void clockevent_set_clock(struct clock_event_device *cd, - unsigned int clock); +static inline void clocksource_set_clock(struct clocksource *cs, + unsigned int clock) +{ + clocksource_calc_mult_shift(cs, clock, 4); +} + +static inline void clockevent_set_clock(struct clock_event_device *cd, + unsigned int clock) +{ + clockevents_calc_mult_shift(cd, clock, 4); +} #endif /* _ASM_TIME_H */ diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 1f467d534642..fb7497405510 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -71,39 +71,6 @@ EXPORT_SYMBOL(perf_irq); unsigned int mips_hpt_frequency; -void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) -{ - u64 temp; - u32 shift; - - /* Find a shift value */ - for (shift = 32; shift > 0; shift--) { - temp = (u64) NSEC_PER_SEC << shift; - do_div(temp, clock); - if ((temp >> 32) == 0) - break; - } - cs->shift = shift; - cs->mult = (u32) temp; -} - -void __cpuinit clockevent_set_clock(struct clock_event_device *cd, - unsigned int clock) -{ - u64 temp; - u32 shift; - - /* Find a shift value */ - for (shift = 32; shift > 0; shift--) { - temp = (u64) clock << shift; - do_div(temp, NSEC_PER_SEC); - if ((temp >> 32) == 0) - break; - } - cd->shift = shift; - cd->mult = (u32) temp; -} - /* * This function exists in order to cause an error due to a duplicate * definition if platform code should have its own implementation. The hook diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 892cce82867e..ec8a21df1142 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -275,16 +275,12 @@ asmlinkage long sys_execve(char __user *name, char *filename; int error; - lock_kernel(); - filename = getname(name); error = PTR_ERR(filename); - if (!IS_ERR(filename)) { - error = do_execve(filename, argv, envp, __frame); - putname(filename); - } - - unlock_kernel(); + if (IS_ERR(filename)) + return error; + error = do_execve(filename, argv, envp, __frame); + putname(filename); return error; } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 36707dec94d7..674800b242d6 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -834,7 +834,8 @@ static cycle_t timebase_read(struct clocksource *cs) return (cycle_t)get_tb(); } -void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, + u32 mult) { u64 t2x, stamp_xsec; @@ -847,7 +848,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) /* XXX this assumes clock->shift == 22 */ /* 4611686018 ~= 2^(20+64-22) / 1e9 */ - t2x = (u64) clock->mult * 4611686018ULL; + t2x = (u64) mult * 4611686018ULL; stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; do_div(stamp_xsec, 1000000000); stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; @@ -924,7 +925,7 @@ static void register_decrementer_clockevent(int cpu) *dec = decrementer_clockevent; dec->cpumask = cpumask_of(cpu); - printk(KERN_DEBUG "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n", + printk(KERN_DEBUG "clockevent: %s mult[%x] shift[%d] cpu[%d]\n", dec->name, dec->mult, dec->shift, cpu); clockevents_register_device(dec); diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 16c673096a22..c80235206c01 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -220,23 +220,8 @@ config AUDIT_ARCH bool default y -config S390_SWITCH_AMODE - bool "Switch kernel/user addressing modes" - help - This option allows to switch the addressing modes of kernel and user - space. The kernel parameter switch_amode=on will enable this feature, - default is disabled. Enabling this (via kernel parameter) on machines - earlier than IBM System z9-109 EC/BC will reduce system performance. - - Note that this option will also be selected by selecting the execute - protection option below. Enabling the execute protection via the - noexec kernel parameter will also switch the addressing modes, - independent of the switch_amode kernel parameter. - - config S390_EXEC_PROTECT bool "Data execute protection" - select S390_SWITCH_AMODE help This option allows to enable a buffer overflow protection for user space programs and it also selects the addressing mode option above. diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index b49c00ce65e9..a3209906739e 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c @@ -6,7 +6,6 @@ #include <linux/fs.h> #include <linux/init.h> #include <linux/kernel.h> -#include <linux/smp_lock.h> #include <linux/miscdevice.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -49,7 +48,6 @@ static unsigned char parm_block[32] = { static int prng_open(struct inode *inode, struct file *file) { - cycle_kernel_lock(); return nonseekable_open(inode, file); } diff --git a/arch/s390/defconfig b/arch/s390/defconfig index ab4464486b7a..f4e53c6708dc 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -185,7 +185,6 @@ CONFIG_HOTPLUG_CPU=y CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_AUDIT_ARCH=y -CONFIG_S390_SWITCH_AMODE=y CONFIG_S390_EXEC_PROTECT=y # diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index ae7c8f9f94a5..2a113d6a7dfd 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -21,7 +21,7 @@ #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) #define __CS_LOOP(ptr, op_val, op_string) ({ \ - typeof(ptr->counter) old_val, new_val; \ + int old_val, new_val; \ asm volatile( \ " l %0,%2\n" \ "0: lr %1,%0\n" \ @@ -38,7 +38,7 @@ #else /* __GNUC__ */ #define __CS_LOOP(ptr, op_val, op_string) ({ \ - typeof(ptr->counter) old_val, new_val; \ + int old_val, new_val; \ asm volatile( \ " l %0,0(%3)\n" \ "0: lr %1,%0\n" \ @@ -143,7 +143,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) #define __CSG_LOOP(ptr, op_val, op_string) ({ \ - typeof(ptr->counter) old_val, new_val; \ + long long old_val, new_val; \ asm volatile( \ " lg %0,%2\n" \ "0: lgr %1,%0\n" \ @@ -160,7 +160,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #else /* __GNUC__ */ #define __CSG_LOOP(ptr, op_val, op_string) ({ \ - typeof(ptr->counter) old_val, new_val; \ + long long old_val, new_val; \ asm volatile( \ " lg %0,0(%3)\n" \ "0: lgr %1,%0\n" \ diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index 2a5419551176..f4bd346a52d3 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h @@ -142,6 +142,8 @@ struct ccw1; extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long); extern int ccw_device_set_options(struct ccw_device *, unsigned long); extern void ccw_device_clear_options(struct ccw_device *, unsigned long); +int ccw_device_is_pathgroup(struct ccw_device *cdev); +int ccw_device_is_multipath(struct ccw_device *cdev); /* Allow for i/o completion notification after primary interrupt status. */ #define CCWDEV_EARLY_NOTIFICATION 0x0001 @@ -151,6 +153,8 @@ extern void ccw_device_clear_options(struct ccw_device *, unsigned long); #define CCWDEV_DO_PATHGROUP 0x0004 /* Allow forced onlining of boxed devices. */ #define CCWDEV_ALLOW_FORCE 0x0008 +/* Try to use multipath mode. */ +#define CCWDEV_DO_MULTIPATH 0x0010 extern int ccw_device_start(struct ccw_device *, struct ccw1 *, unsigned long, __u8, unsigned long); diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index f23961ada7fb..258ba88b7b50 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -183,6 +183,7 @@ struct s390_idle_data { unsigned long long idle_count; unsigned long long idle_enter; unsigned long long idle_time; + int nohz_delay; }; DECLARE_PER_CPU(struct s390_idle_data, s390_idle); @@ -198,4 +199,11 @@ static inline void s390_idle_check(void) vtime_start_cpu(); } +static inline int s390_nohz_delay(int cpu) +{ + return per_cpu(s390_idle, cpu).nohz_delay != 0; +} + +#define arch_needs_cpu(cpu) s390_nohz_delay(cpu) + #endif /* _S390_CPUTIME_H */ diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index fc7edd6f41b6..976e273988c2 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -36,7 +36,7 @@ static inline int init_new_context(struct task_struct *tsk, mm->context.has_pgste = 1; mm->context.alloc_pgste = 1; } else { - mm->context.noexec = s390_noexec; + mm->context.noexec = (user_mode == SECONDARY_SPACE_MODE); mm->context.has_pgste = 0; mm->context.alloc_pgste = 0; } @@ -58,7 +58,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) pgd_t *pgd = mm->pgd; S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); - if (switch_amode) { + if (user_mode != HOME_SPACE_MODE) { /* Load primary space page table origin. */ pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd; S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd); diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index ddad5903341c..68940d0bad91 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h @@ -143,7 +143,8 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) spin_lock_init(&mm->context.list_lock); INIT_LIST_HEAD(&mm->context.crst_list); INIT_LIST_HEAD(&mm->context.pgtable_list); - return (pgd_t *) crst_table_alloc(mm, s390_noexec); + return (pgd_t *) + crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE); } #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 60a7b1a1702f..e2fa79cf0614 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -169,12 +169,13 @@ extern unsigned long VMALLOC_START; * STL Segment-Table-Length: Segment-table length (STL+1*16 entries -> up to 2048) * * A 64 bit pagetable entry of S390 has following format: - * | PFRA |0IP0| OS | + * | PFRA |0IPC| OS | * 0000000000111111111122222222223333333333444444444455555555556666 * 0123456789012345678901234567890123456789012345678901234567890123 * * I Page-Invalid Bit: Page is not available for address-translation * P Page-Protection Bit: Store access not possible for page + * C Change-bit override: HW is not required to set change bit * * A 64 bit segmenttable entry of S390 has following format: * | P-table origin | TT @@ -218,6 +219,7 @@ extern unsigned long VMALLOC_START; */ /* Hardware bits in the page table entry */ +#define _PAGE_CO 0x100 /* HW Change-bit override */ #define _PAGE_RO 0x200 /* HW read-only bit */ #define _PAGE_INVALID 0x400 /* HW invalid bit */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index e37478e87286..52a779c337e8 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -49,17 +49,12 @@ extern unsigned long memory_end; void detect_memory_layout(struct mem_chunk chunk[]); -#ifdef CONFIG_S390_SWITCH_AMODE -extern unsigned int switch_amode; -#else -#define switch_amode (0) -#endif - -#ifdef CONFIG_S390_EXEC_PROTECT -extern unsigned int s390_noexec; -#else -#define s390_noexec (0) -#endif +#define PRIMARY_SPACE_MODE 0 +#define ACCESS_REGISTER_MODE 1 +#define SECONDARY_SPACE_MODE 2 +#define HOME_SPACE_MODE 3 + +extern unsigned int user_mode; /* * Machine features detected in head.S diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index a868b272c257..2ab1141eeb50 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -1,57 +1,22 @@ /* - * include/asm-s390/smp.h - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), - * Martin Schwidefsky (schwidefsky@de.ibm.com) - * Heiko Carstens (heiko.carstens@de.ibm.com) + * Copyright IBM Corp. 1999,2009 + * Author(s): Denis Joseph Barrow, + * Martin Schwidefsky <schwidefsky@de.ibm.com>, + * Heiko Carstens <heiko.carstens@de.ibm.com>, */ #ifndef __ASM_SMP_H #define __ASM_SMP_H -#include <linux/threads.h> -#include <linux/cpumask.h> -#include <linux/bitops.h> +#ifdef CONFIG_SMP -#if defined(__KERNEL__) && defined(CONFIG_SMP) && !defined(__ASSEMBLY__) - -#include <asm/lowcore.h> -#include <asm/sigp.h> -#include <asm/ptrace.h> #include <asm/system.h> - -/* - s390 specific smp.c headers - */ -typedef struct -{ - int intresting; - sigp_ccode ccode; - __u32 status; - __u16 cpu; -} sigp_info; +#include <asm/sigp.h> extern void machine_restart_smp(char *); extern void machine_halt_smp(void); extern void machine_power_off_smp(void); -#define NO_PROC_ID 0xFF /* No processor magic marker */ - -/* - * This magic constant controls our willingness to transfer - * a process across CPUs. Such a transfer incurs misses on the L1 - * cache, and on a P6 or P5 with multiple L2 caches L2 hits. My - * gut feeling is this will vary by board in value. For a board - * with separate L2 cache it probably depends also on the RSS, and - * for a board with shared L2 cache it ought to decay fast as other - * processes are run. - */ - -#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */ - #define raw_smp_processor_id() (S390_lowcore.cpu_nr) -#define cpu_logical_map(cpu) (cpu) extern int __cpu_disable (void); extern void __cpu_die (unsigned int cpu); @@ -64,7 +29,9 @@ extern int smp_cpu_polarization[]; extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); -#endif +extern union save_area *zfcpdump_save_areas[NR_CPUS + 1]; + +#endif /* CONFIG_SMP */ #ifdef CONFIG_HOTPLUG_CPU extern int smp_rescan_cpus(void); @@ -72,5 +39,4 @@ extern int smp_rescan_cpus(void); static inline int smp_rescan_cpus(void) { return 0; } #endif -extern union save_area *zfcpdump_save_areas[NR_CPUS + 1]; -#endif +#endif /* __ASM_SMP_H */ diff --git a/arch/s390/include/asm/sockios.h b/arch/s390/include/asm/sockios.h index f4fc16c7da59..6f60eee73242 100644 --- a/arch/s390/include/asm/sockios.h +++ b/arch/s390/include/asm/sockios.h @@ -1,21 +1,6 @@ -/* - * include/asm-s390/sockios.h - * - * S390 version - * - * Derived from "include/asm-i386/sockios.h" - */ +#ifndef _ASM_S390_SOCKIOS_H +#define _ASM_S390_SOCKIOS_H -#ifndef __ARCH_S390_SOCKIOS__ -#define __ARCH_S390_SOCKIOS__ - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ -#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ +#include <asm-generic/sockios.h> #endif diff --git a/arch/s390/include/asm/termbits.h b/arch/s390/include/asm/termbits.h index 58731853d529..71bf6ac6a2b9 100644 --- a/arch/s390/include/asm/termbits.h +++ b/arch/s390/include/asm/termbits.h @@ -1,206 +1,6 @@ -/* - * include/asm-s390/termbits.h - * - * S390 version - * - * Derived from "include/asm-i386/termbits.h" - */ +#ifndef _ASM_S390_TERMBITS_H +#define _ASM_S390_TERMBITS_H -#ifndef __ARCH_S390_TERMBITS_H__ -#define __ARCH_S390_TERMBITS_H__ - -#include <linux/posix_types.h> - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ -}; - -struct termios2 { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -struct ktermios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -/* c_iflag bits */ -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define XTABS 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -/* c_cflag bit meaning */ -#define CBAUD 0010017 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 -#define CBAUDEX 0010000 -#define BOTHER 0010000 -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate */ -#define CMSPAR 010000000000 /* mark or space (stick) parity */ -#define CRTSCTS 020000000000 /* flow control */ - -#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 - -/* tcflow() and TCXONC use these */ -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 +#include <asm-generic/termbits.h> #endif diff --git a/arch/s390/include/asm/todclk.h b/arch/s390/include/asm/todclk.h deleted file mode 100644 index c7f62055488a..000000000000 --- a/arch/s390/include/asm/todclk.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * File...........: linux/include/asm/todclk.h - * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> - * Bugreports.to..: <Linux390@de.ibm.com> - * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 - * - * History of changes (starts July 2000) - */ - -#ifndef __ASM_TODCLK_H -#define __ASM_TODCLK_H - -#ifdef __KERNEL__ - -#define TOD_uSEC (0x1000ULL) -#define TOD_mSEC (1000 * TOD_uSEC) -#define TOD_SEC (1000 * TOD_mSEC) -#define TOD_MIN (60 * TOD_SEC) -#define TOD_HOUR (60 * TOD_MIN) - -#endif - -#endif diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 8377e91533d2..cbf0a8745bf4 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -93,6 +93,8 @@ extern struct uaccess_ops uaccess_mvcos; extern struct uaccess_ops uaccess_mvcos_switch; extern struct uaccess_ops uaccess_pt; +extern int __handle_fault(unsigned long, unsigned long, int); + static inline int __put_user_fn(size_t size, void __user *ptr, void *x) { size = uaccess.copy_to_user_small(size, ptr, x); diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index c7be8e10b87e..683f6381cc59 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_FUNCTION_TRACER) += $(if $(CONFIG_64BIT),mcount64.o,mcount.o) obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o +obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index fda1a8123f9b..25c31d681402 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -31,14 +31,8 @@ #include <linux/shm.h> #include <linux/slab.h> #include <linux/uio.h> -#include <linux/nfs_fs.h> #include <linux/quota.h> #include <linux/module.h> -#include <linux/sunrpc/svc.h> -#include <linux/nfsd/nfsd.h> -#include <linux/nfsd/cache.h> -#include <linux/nfsd/xdr.h> -#include <linux/nfsd/syscall.h> #include <linux/poll.h> #include <linux/personality.h> #include <linux/stat.h> diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 45e9092b3aad..cb97afc85c94 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -4,10 +4,6 @@ #include <linux/compat.h> #include <linux/socket.h> #include <linux/syscalls.h> -#include <linux/nfs_fs.h> -#include <linux/sunrpc/svc.h> -#include <linux/nfsd/nfsd.h> -#include <linux/nfsd/export.h> /* Macro that masks the high order bit of an 32 bit pointer and converts it*/ /* to a 64 bit pointer */ diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 6a250808092b..d984a2a380c3 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -83,6 +83,8 @@ startup_continue: slr %r0,%r0 # set cpuid to zero sigp %r1,%r0,0x12 # switch to esame mode sam64 # switch to 64 bit mode + llgfr %r13,%r13 # clear high-order half of base reg + lmh %r0,%r15,.Lzero64-.LPG1(%r13) # clear high-order half lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area # move IPL device to lowcore @@ -127,6 +129,7 @@ startup_continue: .L4malign:.quad 0xffffffffffc00000 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 .Lnop: .long 0x07000700 +.Lzero64:.fill 16,4,0x0 #ifdef CONFIG_ZFCPDUMP .Lcurrent_cpu: .long 0x0 diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index 0de305b598ce..59618bcd99b7 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c @@ -126,6 +126,8 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code) /* Serve timer interrupts first. */ clock_comparator_work(); kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; + if (code != 0x1004) + __get_cpu_var(s390_idle).nohz_delay = 1; index = ext_hash(code); for (p = ext_int_hash[index]; p; p = p->next) { if (likely(p->code == code)) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 061479ff029f..0663287fa1b3 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -305,9 +305,8 @@ static int __init early_parse_mem(char *p) } early_param("mem", early_parse_mem); -#ifdef CONFIG_S390_SWITCH_AMODE -unsigned int switch_amode = 0; -EXPORT_SYMBOL_GPL(switch_amode); +unsigned int user_mode = HOME_SPACE_MODE; +EXPORT_SYMBOL_GPL(user_mode); static int set_amode_and_uaccess(unsigned long user_amode, unsigned long user32_amode) @@ -340,23 +339,29 @@ static int set_amode_and_uaccess(unsigned long user_amode, */ static int __init early_parse_switch_amode(char *p) { - switch_amode = 1; + if (user_mode != SECONDARY_SPACE_MODE) + user_mode = PRIMARY_SPACE_MODE; return 0; } early_param("switch_amode", early_parse_switch_amode); -#else /* CONFIG_S390_SWITCH_AMODE */ -static inline int set_amode_and_uaccess(unsigned long user_amode, - unsigned long user32_amode) +static int __init early_parse_user_mode(char *p) { + if (p && strcmp(p, "primary") == 0) + user_mode = PRIMARY_SPACE_MODE; +#ifdef CONFIG_S390_EXEC_PROTECT + else if (p && strcmp(p, "secondary") == 0) + user_mode = SECONDARY_SPACE_MODE; +#endif + else if (!p || strcmp(p, "home") == 0) + user_mode = HOME_SPACE_MODE; + else + return 1; return 0; } -#endif /* CONFIG_S390_SWITCH_AMODE */ +early_param("user_mode", early_parse_user_mode); #ifdef CONFIG_S390_EXEC_PROTECT -unsigned int s390_noexec = 0; -EXPORT_SYMBOL_GPL(s390_noexec); - /* * Enable execute protection? */ @@ -364,8 +369,7 @@ static int __init early_parse_noexec(char *p) { if (!strncmp(p, "off", 3)) return 0; - switch_amode = 1; - s390_noexec = 1; + user_mode = SECONDARY_SPACE_MODE; return 0; } early_param("noexec", early_parse_noexec); @@ -373,7 +377,7 @@ early_param("noexec", early_parse_noexec); static void setup_addressing_mode(void) { - if (s390_noexec) { + if (user_mode == SECONDARY_SPACE_MODE) { if (set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY)) pr_info("Execute protection active, " @@ -381,7 +385,7 @@ static void setup_addressing_mode(void) else pr_info("Execute protection active, " "mvcos not available\n"); - } else if (switch_amode) { + } else if (user_mode == PRIMARY_SPACE_MODE) { if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) pr_info("Address spaces switched, " "mvcos available\n"); @@ -411,7 +415,7 @@ setup_lowcore(void) lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) restart_int_handler; - if (switch_amode) + if (user_mode != HOME_SPACE_MODE) lc->restart_psw.mask |= PSW_ASC_HOME; lc->external_new_psw.mask = psw_kernel_bits; lc->external_new_psw.addr = diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 34162a0b2caa..65065ac48ed3 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -214,7 +214,8 @@ struct clocksource * __init clocksource_default_clock(void) return &clocksource_tod; } -void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, + u32 mult) { if (clock != &clocksource_tod) return; @@ -334,7 +335,7 @@ int get_sync_clock(unsigned long long *clock) sw0 = atomic_read(sw_ptr); *clock = get_clock(); sw1 = atomic_read(sw_ptr); - put_cpu_var(clock_sync_sync); + put_cpu_var(clock_sync_word); if (sw0 == sw1 && (sw0 & 0x80000000U)) /* Success: time is in sync. */ return 0; @@ -384,7 +385,7 @@ static inline int check_sync_clock(void) sw_ptr = &get_cpu_var(clock_sync_word); rc = (atomic_read(sw_ptr) & 0x80000000U) != 0; - put_cpu_var(clock_sync_sync); + put_cpu_var(clock_sync_word); return rc; } diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index adfb32aa6d59..5f99e66c51c3 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -86,7 +86,8 @@ static void vdso_init_data(struct vdso_data *vd) unsigned int facility_list; facility_list = stfl(); - vd->ectg_available = switch_amode && (facility_list & 1); + vd->ectg_available = + user_mode != HOME_SPACE_MODE && (facility_list & 1); } #ifdef CONFIG_64BIT @@ -114,7 +115,7 @@ int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore) lowcore->vdso_per_cpu_data = __LC_PASTE; - if (!switch_amode || !vdso_enabled) + if (user_mode == HOME_SPACE_MODE || !vdso_enabled) return 0; segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); @@ -160,7 +161,7 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) unsigned long segment_table, page_table, page_frame; u32 *psal, *aste; - if (!switch_amode || !vdso_enabled) + if (user_mode == HOME_SPACE_MODE || !vdso_enabled) return; psal = (u32 *)(addr_t) lowcore->paste[4]; @@ -184,7 +185,7 @@ static void __vdso_init_cr5(void *dummy) static void vdso_init_cr5(void) { - if (switch_amode && vdso_enabled) + if (user_mode != HOME_SPACE_MODE && vdso_enabled) on_each_cpu(__vdso_init_cr5, NULL, 1); } #endif /* CONFIG_64BIT */ diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index c41bb0d416e1..b59a812a010e 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -167,6 +167,8 @@ void vtime_stop_cpu(void) /* Wait for external, I/O or machine check interrupt. */ psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT; + idle->nohz_delay = 0; + /* Check if the CPU timer needs to be reprogrammed. */ if (vq->do_spt) { __u64 vmax = VTIMER_MAX_SLICE; diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index bf164fc21864..6ee55ae84ce2 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -20,7 +20,6 @@ config KVM depends on HAVE_KVM && EXPERIMENTAL select PREEMPT_NOTIFIERS select ANON_INODES - select S390_SWITCH_AMODE ---help--- Support hosting paravirtualized guest machines using the SIE virtualization capability on the mainframe. This should work diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c index 58da3f461214..60455f104ea3 100644 --- a/arch/s390/lib/uaccess_mvcos.c +++ b/arch/s390/lib/uaccess_mvcos.c @@ -162,7 +162,6 @@ static size_t clear_user_mvcos(size_t size, void __user *to) return size; } -#ifdef CONFIG_S390_SWITCH_AMODE static size_t strnlen_user_mvcos(size_t count, const char __user *src) { char buf[256]; @@ -200,7 +199,6 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src, } while ((len_str == len) && (done < count)); return done; } -#endif /* CONFIG_S390_SWITCH_AMODE */ struct uaccess_ops uaccess_mvcos = { .copy_from_user = copy_from_user_mvcos_check, @@ -215,7 +213,6 @@ struct uaccess_ops uaccess_mvcos = { .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std, }; -#ifdef CONFIG_S390_SWITCH_AMODE struct uaccess_ops uaccess_mvcos_switch = { .copy_from_user = copy_from_user_mvcos, .copy_from_user_small = copy_from_user_mvcos, @@ -228,4 +225,3 @@ struct uaccess_ops uaccess_mvcos_switch = { .futex_atomic_op = futex_atomic_op_pt, .futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt, }; -#endif diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index cb5d59eab0ee..404f2de296dc 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c @@ -23,86 +23,21 @@ static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr) pgd = pgd_offset(mm, addr); if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - return NULL; + return (pte_t *) 0x3a; pud = pud_offset(pgd, addr); if (pud_none(*pud) || unlikely(pud_bad(*pud))) - return NULL; + return (pte_t *) 0x3b; pmd = pmd_offset(pud, addr); if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) - return NULL; + return (pte_t *) 0x10; return pte_offset_map(pmd, addr); } -static int __handle_fault(struct mm_struct *mm, unsigned long address, - int write_access) -{ - struct vm_area_struct *vma; - int ret = -EFAULT; - int fault; - - if (in_atomic()) - return ret; - down_read(&mm->mmap_sem); - vma = find_vma(mm, address); - if (unlikely(!vma)) - goto out; - if (unlikely(vma->vm_start > address)) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto out; - if (expand_stack(vma, address)) - goto out; - } - - if (!write_access) { - /* page not present, check vm flags */ - if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) - goto out; - } else { - if (!(vma->vm_flags & VM_WRITE)) - goto out; - } - -survive: - fault = handle_mm_fault(mm, vma, address, write_access ? FAULT_FLAG_WRITE : 0); - if (unlikely(fault & VM_FAULT_ERROR)) { - if (fault & VM_FAULT_OOM) - goto out_of_memory; - else if (fault & VM_FAULT_SIGBUS) - goto out_sigbus; - BUG(); - } - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; - ret = 0; -out: - up_read(&mm->mmap_sem); - return ret; - -out_of_memory: - up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", current->comm); - return ret; - -out_sigbus: - up_read(&mm->mmap_sem); - current->thread.prot_addr = address; - current->thread.trap_no = 0x11; - force_sig(SIGBUS, current); - return ret; -} - -static size_t __user_copy_pt(unsigned long uaddr, void *kptr, - size_t n, int write_user) +static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, + size_t n, int write_user) { struct mm_struct *mm = current->mm; unsigned long offset, pfn, done, size; @@ -114,12 +49,17 @@ retry: spin_lock(&mm->page_table_lock); do { pte = follow_table(mm, uaddr); - if (!pte || !pte_present(*pte) || - (write_user && !pte_write(*pte))) + if ((unsigned long) pte < 0x1000) goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; + goto fault; + } else if (write_user && !pte_write(*pte)) { + pte = (pte_t *) 0x04; + goto fault; + } pfn = pte_pfn(*pte); - offset = uaddr & (PAGE_SIZE - 1); size = min(n - done, PAGE_SIZE - offset); if (write_user) { @@ -137,7 +77,7 @@ retry: return n - done; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(mm, uaddr, write_user)) + if (__handle_fault(uaddr, (unsigned long) pte, write_user)) return n - done; goto retry; } @@ -146,30 +86,31 @@ fault: * Do DAT for user address by page table walk, return kernel address. * This function needs to be called with current->mm->page_table_lock held. */ -static unsigned long __dat_user_addr(unsigned long uaddr) +static __always_inline unsigned long __dat_user_addr(unsigned long uaddr) { struct mm_struct *mm = current->mm; - unsigned long pfn, ret; + unsigned long pfn; pte_t *pte; int rc; - ret = 0; retry: pte = follow_table(mm, uaddr); - if (!pte || !pte_present(*pte)) + if ((unsigned long) pte < 0x1000) goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; + goto fault; + } pfn = pte_pfn(*pte); - ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); -out: - return ret; + return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); fault: spin_unlock(&mm->page_table_lock); - rc = __handle_fault(mm, uaddr, 0); + rc = __handle_fault(uaddr, (unsigned long) pte, 0); spin_lock(&mm->page_table_lock); - if (rc) - goto out; - goto retry; + if (!rc) + goto retry; + return 0; } size_t copy_from_user_pt(size_t n, const void __user *from, void *to) @@ -234,8 +175,12 @@ retry: spin_lock(&mm->page_table_lock); do { pte = follow_table(mm, uaddr); - if (!pte || !pte_present(*pte)) + if ((unsigned long) pte < 0x1000) + goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; goto fault; + } pfn = pte_pfn(*pte); offset = uaddr & (PAGE_SIZE-1); @@ -249,9 +194,8 @@ retry: return done + 1; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(mm, uaddr, 0)) { + if (__handle_fault(uaddr, (unsigned long) pte, 0)) return 0; - } goto retry; } @@ -284,7 +228,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to, { struct mm_struct *mm = current->mm; unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to, - uaddr, done, size; + uaddr, done, size, error_code; unsigned long uaddr_from = (unsigned long) from; unsigned long uaddr_to = (unsigned long) to; pte_t *pte_from, *pte_to; @@ -298,17 +242,28 @@ static size_t copy_in_user_pt(size_t n, void __user *to, retry: spin_lock(&mm->page_table_lock); do { + write_user = 0; + uaddr = uaddr_from; pte_from = follow_table(mm, uaddr_from); - if (!pte_from || !pte_present(*pte_from)) { - uaddr = uaddr_from; - write_user = 0; + error_code = (unsigned long) pte_from; + if (error_code < 0x1000) + goto fault; + if (!pte_present(*pte_from)) { + error_code = 0x11; goto fault; } + write_user = 1; + uaddr = uaddr_to; pte_to = follow_table(mm, uaddr_to); - if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) { - uaddr = uaddr_to; - write_user = 1; + error_code = (unsigned long) pte_to; + if (error_code < 0x1000) + goto fault; + if (!pte_present(*pte_to)) { + error_code = 0x11; + goto fault; + } else if (!pte_write(*pte_to)) { + error_code = 0x04; goto fault; } @@ -329,7 +284,7 @@ retry: return n - done; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(mm, uaddr, write_user)) + if (__handle_fault(uaddr, error_code, write_user)) return n - done; goto retry; } diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index ff58779bf7e9..76a3637b88e0 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -18,6 +18,7 @@ #include <linux/swap.h> #include <linux/kthread.h> #include <linux/oom.h> +#include <linux/suspend.h> #include <asm/pgalloc.h> #include <asm/uaccess.h> @@ -44,6 +45,7 @@ static volatile long cmm_pages_target; static volatile long cmm_timed_pages_target; static long cmm_timeout_pages; static long cmm_timeout_seconds; +static int cmm_suspended; static struct cmm_page_array *cmm_page_list; static struct cmm_page_array *cmm_timed_page_list; @@ -147,9 +149,9 @@ cmm_thread(void *dummy) while (1) { rc = wait_event_interruptible(cmm_thread_wait, - (cmm_pages != cmm_pages_target || - cmm_timed_pages != cmm_timed_pages_target || - kthread_should_stop())); + (!cmm_suspended && (cmm_pages != cmm_pages_target || + cmm_timed_pages != cmm_timed_pages_target)) || + kthread_should_stop()); if (kthread_should_stop() || rc == -ERESTARTSYS) { cmm_pages_target = cmm_pages; cmm_timed_pages_target = cmm_timed_pages; @@ -410,6 +412,38 @@ cmm_smsg_target(char *from, char *msg) static struct ctl_table_header *cmm_sysctl_header; +static int cmm_suspend(void) +{ + cmm_suspended = 1; + cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); + cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); + return 0; +} + +static int cmm_resume(void) +{ + cmm_suspended = 0; + cmm_kick_thread(); + return 0; +} + +static int cmm_power_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + switch (event) { + case PM_POST_HIBERNATION: + return cmm_resume(); + case PM_HIBERNATION_PREPARE: + return cmm_suspend(); + default: + return NOTIFY_DONE; + } +} + +static struct notifier_block cmm_power_notifier = { + .notifier_call = cmm_power_event, +}; + static int cmm_init (void) { @@ -418,7 +452,7 @@ cmm_init (void) #ifdef CONFIG_CMM_PROC cmm_sysctl_header = register_sysctl_table(cmm_dir_table); if (!cmm_sysctl_header) - goto out; + goto out_sysctl; #endif #ifdef CONFIG_CMM_IUCV rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); @@ -428,17 +462,21 @@ cmm_init (void) rc = register_oom_notifier(&cmm_oom_nb); if (rc < 0) goto out_oom_notify; + rc = register_pm_notifier(&cmm_power_notifier); + if (rc) + goto out_pm; init_waitqueue_head(&cmm_thread_wait); init_timer(&cmm_timer); cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0; - if (!rc) - goto out; - /* - * kthread_create failed. undo all the stuff from above again. - */ - unregister_oom_notifier(&cmm_oom_nb); + if (rc) + goto out_kthread; + return 0; +out_kthread: + unregister_pm_notifier(&cmm_power_notifier); +out_pm: + unregister_oom_notifier(&cmm_oom_nb); out_oom_notify: #ifdef CONFIG_CMM_IUCV smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); @@ -446,8 +484,8 @@ out_smsg: #endif #ifdef CONFIG_CMM_PROC unregister_sysctl_table(cmm_sysctl_header); +out_sysctl: #endif -out: return rc; } @@ -455,6 +493,7 @@ static void cmm_exit(void) { kthread_stop(cmm_thread_ptr); + unregister_pm_notifier(&cmm_power_notifier); unregister_oom_notifier(&cmm_oom_nb); cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 6d507462967a..fc102e70d9c2 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -34,16 +34,15 @@ #include <asm/pgtable.h> #include <asm/s390_ext.h> #include <asm/mmu_context.h> +#include <asm/compat.h> #include "../kernel/entry.h" #ifndef CONFIG_64BIT #define __FAIL_ADDR_MASK 0x7ffff000 -#define __FIXUP_MASK 0x7fffffff #define __SUBCODE_MASK 0x0200 #define __PF_RES_FIELD 0ULL #else /* CONFIG_64BIT */ #define __FAIL_ADDR_MASK -4096L -#define __FIXUP_MASK ~0L #define __SUBCODE_MASK 0x0600 #define __PF_RES_FIELD 0x8000000000000000ULL #endif /* CONFIG_64BIT */ @@ -52,11 +51,15 @@ extern int sysctl_userprocess_debug; #endif -#ifdef CONFIG_KPROBES -static inline int notify_page_fault(struct pt_regs *regs, long err) +#define VM_FAULT_BADCONTEXT 0x010000 +#define VM_FAULT_BADMAP 0x020000 +#define VM_FAULT_BADACCESS 0x040000 + +static inline int notify_page_fault(struct pt_regs *regs) { int ret = 0; +#ifdef CONFIG_KPROBES /* kprobe_running() needs smp_processor_id() */ if (!user_mode(regs)) { preempt_disable(); @@ -64,15 +67,9 @@ static inline int notify_page_fault(struct pt_regs *regs, long err) ret = 1; preempt_enable(); } - +#endif return ret; } -#else -static inline int notify_page_fault(struct pt_regs *regs, long err) -{ - return 0; -} -#endif /* @@ -100,57 +97,50 @@ void bust_spinlocks(int yes) /* * Returns the address space associated with the fault. - * Returns 0 for kernel space, 1 for user space and - * 2 for code execution in user space with noexec=on. + * Returns 0 for kernel space and 1 for user space. */ -static inline int check_space(struct task_struct *tsk) +static inline int user_space_fault(unsigned long trans_exc_code) { /* - * The lowest two bits of S390_lowcore.trans_exc_code - * indicate which paging table was used. + * The lowest two bits of the translation exception + * identification indicate which paging table was used. */ - int desc = S390_lowcore.trans_exc_code & 3; - - if (desc == 3) /* Home Segment Table Descriptor */ - return switch_amode == 0; - if (desc == 2) /* Secondary Segment Table Descriptor */ - return tsk->thread.mm_segment.ar4; -#ifdef CONFIG_S390_SWITCH_AMODE - if (unlikely(desc == 1)) { /* STD determined via access register */ - /* %a0 always indicates primary space. */ - if (S390_lowcore.exc_access_id != 0) { - save_access_regs(tsk->thread.acrs); - /* - * An alet of 0 indicates primary space. - * An alet of 1 indicates secondary space. - * Any other alet values generate an - * alen-translation exception. - */ - if (tsk->thread.acrs[S390_lowcore.exc_access_id]) - return tsk->thread.mm_segment.ar4; - } - } -#endif - /* Primary Segment Table Descriptor */ - return switch_amode << s390_noexec; + trans_exc_code &= 3; + if (trans_exc_code == 2) + /* Access via secondary space, set_fs setting decides */ + return current->thread.mm_segment.ar4; + if (user_mode == HOME_SPACE_MODE) + /* User space if the access has been done via home space. */ + return trans_exc_code == 3; + /* + * If the user space is not the home space the kernel runs in home + * space. Access via secondary space has already been covered, + * access via primary space or access register is from user space + * and access via home space is from the kernel. + */ + return trans_exc_code != 3; } /* * Send SIGSEGV to task. This is an external routine * to keep the stack usage of do_page_fault small. */ -static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, - int si_code, unsigned long address) +static noinline void do_sigsegv(struct pt_regs *regs, long int_code, + int si_code, unsigned long trans_exc_code) { struct siginfo si; + unsigned long address; + address = trans_exc_code & __FAIL_ADDR_MASK; + current->thread.prot_addr = address; + current->thread.trap_no = int_code; #if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) #if defined(CONFIG_SYSCTL) if (sysctl_userprocess_debug) #endif { printk("User process fault: interruption code 0x%lX\n", - error_code); + int_code); printk("failing address: %lX\n", address); show_regs(regs); } @@ -161,13 +151,14 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, force_sig_info(SIGSEGV, &si, current); } -static void do_no_context(struct pt_regs *regs, unsigned long error_code, - unsigned long address) +static noinline void do_no_context(struct pt_regs *regs, long int_code, + unsigned long trans_exc_code) { const struct exception_table_entry *fixup; + unsigned long address; /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->psw.addr & __FIXUP_MASK); + fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); if (fixup) { regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; return; @@ -177,129 +168,149 @@ static void do_no_context(struct pt_regs *regs, unsigned long error_code, * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ - if (check_space(current) == 0) + address = trans_exc_code & __FAIL_ADDR_MASK; + if (!user_space_fault(trans_exc_code)) printk(KERN_ALERT "Unable to handle kernel pointer dereference" " at virtual kernel address %p\n", (void *)address); else printk(KERN_ALERT "Unable to handle kernel paging request" " at virtual user address %p\n", (void *)address); - die("Oops", regs, error_code); + die("Oops", regs, int_code); do_exit(SIGKILL); } -static void do_low_address(struct pt_regs *regs, unsigned long error_code) +static noinline void do_low_address(struct pt_regs *regs, long int_code, + unsigned long trans_exc_code) { /* Low-address protection hit in kernel mode means NULL pointer write access in kernel mode. */ if (regs->psw.mask & PSW_MASK_PSTATE) { /* Low-address protection hit in user mode 'cannot happen'. */ - die ("Low-address protection", regs, error_code); + die ("Low-address protection", regs, int_code); do_exit(SIGKILL); } - do_no_context(regs, error_code, 0); + do_no_context(regs, int_code, trans_exc_code); } -static void do_sigbus(struct pt_regs *regs, unsigned long error_code, - unsigned long address) +static noinline void do_sigbus(struct pt_regs *regs, long int_code, + unsigned long trans_exc_code) { struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; - up_read(&mm->mmap_sem); /* * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->thread.prot_addr = address; - tsk->thread.trap_no = error_code; + tsk->thread.prot_addr = trans_exc_code & __FAIL_ADDR_MASK; + tsk->thread.trap_no = int_code; force_sig(SIGBUS, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!(regs->psw.mask & PSW_MASK_PSTATE)) - do_no_context(regs, error_code, address); } #ifdef CONFIG_S390_EXEC_PROTECT -static int signal_return(struct mm_struct *mm, struct pt_regs *regs, - unsigned long address, unsigned long error_code) +static noinline int signal_return(struct pt_regs *regs, long int_code, + unsigned long trans_exc_code) { u16 instruction; int rc; -#ifdef CONFIG_COMPAT - int compat; -#endif - pagefault_disable(); rc = __get_user(instruction, (u16 __user *) regs->psw.addr); - pagefault_enable(); - if (rc) - return -EFAULT; - up_read(&mm->mmap_sem); - clear_tsk_thread_flag(current, TIF_SINGLE_STEP); -#ifdef CONFIG_COMPAT - compat = is_compat_task(); - if (compat && instruction == 0x0a77) - sys32_sigreturn(); - else if (compat && instruction == 0x0aad) - sys32_rt_sigreturn(); - else -#endif - if (instruction == 0x0a77) - sys_sigreturn(); - else if (instruction == 0x0aad) - sys_rt_sigreturn(); - else { - current->thread.prot_addr = address; - current->thread.trap_no = error_code; - do_sigsegv(regs, error_code, SEGV_MAPERR, address); - } + if (!rc && instruction == 0x0a77) { + clear_tsk_thread_flag(current, TIF_SINGLE_STEP); + if (is_compat_task()) + sys32_sigreturn(); + else + sys_sigreturn(); + } else if (!rc && instruction == 0x0aad) { + clear_tsk_thread_flag(current, TIF_SINGLE_STEP); + if (is_compat_task()) + sys32_rt_sigreturn(); + else + sys_rt_sigreturn(); + } else + do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code); return 0; } #endif /* CONFIG_S390_EXEC_PROTECT */ +static noinline void do_fault_error(struct pt_regs *regs, long int_code, + unsigned long trans_exc_code, int fault) +{ + int si_code; + + switch (fault) { + case VM_FAULT_BADACCESS: +#ifdef CONFIG_S390_EXEC_PROTECT + if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && + (trans_exc_code & 3) == 0) { + signal_return(regs, int_code, trans_exc_code); + break; + } +#endif /* CONFIG_S390_EXEC_PROTECT */ + case VM_FAULT_BADMAP: + /* Bad memory access. Check if it is kernel or user space. */ + if (regs->psw.mask & PSW_MASK_PSTATE) { + /* User mode accesses just cause a SIGSEGV */ + si_code = (fault == VM_FAULT_BADMAP) ? + SEGV_MAPERR : SEGV_ACCERR; + do_sigsegv(regs, int_code, si_code, trans_exc_code); + return; + } + case VM_FAULT_BADCONTEXT: + do_no_context(regs, int_code, trans_exc_code); + break; + default: /* fault & VM_FAULT_ERROR */ + if (fault & VM_FAULT_OOM) + pagefault_out_of_memory(); + else if (fault & VM_FAULT_SIGBUS) { + do_sigbus(regs, int_code, trans_exc_code); + /* Kernel mode? Handle exceptions or die */ + if (!(regs->psw.mask & PSW_MASK_PSTATE)) + do_no_context(regs, int_code, trans_exc_code); + } else + BUG(); + break; + } +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. * - * error_code: + * interruption code (int_code): * 04 Protection -> Write-Protection (suprression) * 10 Segment translation -> Not present (nullification) * 11 Page translation -> Not present (nullification) * 3b Region third trans. -> Not present (nullification) */ -static inline void -do_exception(struct pt_regs *regs, unsigned long error_code, int write) +static inline int do_exception(struct pt_regs *regs, int access, + unsigned long trans_exc_code) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct *vma; unsigned long address; - int space; - int si_code; int fault; - if (notify_page_fault(regs, error_code)) - return; + if (notify_page_fault(regs)) + return 0; tsk = current; mm = tsk->mm; - /* get the failing address and the affected space */ - address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK; - space = check_space(tsk); - /* * Verify that the fault happened in user space, that * we are not in an interrupt and that there is a * user context. */ - if (unlikely(space == 0 || in_atomic() || !mm)) - goto no_context; + fault = VM_FAULT_BADCONTEXT; + if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) + goto out; + address = trans_exc_code & __FAIL_ADDR_MASK; /* * When we get here, the fault happened in the current * task's user address space, so we can switch on the @@ -309,42 +320,26 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write) perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); down_read(&mm->mmap_sem); - si_code = SEGV_MAPERR; + fault = VM_FAULT_BADMAP; vma = find_vma(mm, address); if (!vma) - goto bad_area; - -#ifdef CONFIG_S390_EXEC_PROTECT - if (unlikely((space == 2) && !(vma->vm_flags & VM_EXEC))) - if (!signal_return(mm, regs, address, error_code)) - /* - * signal_return() has done an up_read(&mm->mmap_sem) - * if it returns 0. - */ - return; -#endif + goto out_up; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - si_code = SEGV_ACCERR; - if (!write) { - /* page not present, check vm flags */ - if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) - goto bad_area; - } else { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; + if (unlikely(vma->vm_start > address)) { + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto out_up; + if (expand_stack(vma, address)) + goto out_up; } + /* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ + fault = VM_FAULT_BADACCESS; + if (unlikely(!(vma->vm_flags & access))) + goto out_up; + if (is_vm_hugetlb_page(vma)) address &= HPAGE_MASK; /* @@ -352,18 +347,11 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); - if (unlikely(fault & VM_FAULT_ERROR)) { - if (fault & VM_FAULT_OOM) { - up_read(&mm->mmap_sem); - pagefault_out_of_memory(); - return; - } else if (fault & VM_FAULT_SIGBUS) { - do_sigbus(regs, error_code, address); - return; - } - BUG(); - } + fault = handle_mm_fault(mm, vma, address, + (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0); + if (unlikely(fault & VM_FAULT_ERROR)) + goto out_up; + if (fault & VM_FAULT_MAJOR) { tsk->maj_flt++; perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, @@ -373,74 +361,69 @@ good_area: perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, regs, address); } - up_read(&mm->mmap_sem); /* * The instruction that caused the program check will * be repeated. Don't signal single step via SIGTRAP. */ clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: + fault = 0; +out_up: up_read(&mm->mmap_sem); - - /* User mode accesses just cause a SIGSEGV */ - if (regs->psw.mask & PSW_MASK_PSTATE) { - tsk->thread.prot_addr = address; - tsk->thread.trap_no = error_code; - do_sigsegv(regs, error_code, si_code, address); - return; - } - -no_context: - do_no_context(regs, error_code, address); +out: + return fault; } -void __kprobes do_protection_exception(struct pt_regs *regs, - long error_code) +void __kprobes do_protection_exception(struct pt_regs *regs, long int_code) { + unsigned long trans_exc_code = S390_lowcore.trans_exc_code; + int fault; + /* Protection exception is supressing, decrement psw address. */ - regs->psw.addr -= (error_code >> 16); + regs->psw.addr -= (int_code >> 16); /* * Check for low-address protection. This needs to be treated * as a special case because the translation exception code * field is not guaranteed to contain valid data in this case. */ - if (unlikely(!(S390_lowcore.trans_exc_code & 4))) { - do_low_address(regs, error_code); + if (unlikely(!(trans_exc_code & 4))) { + do_low_address(regs, int_code, trans_exc_code); return; } - do_exception(regs, 4, 1); + fault = do_exception(regs, VM_WRITE, trans_exc_code); + if (unlikely(fault)) + do_fault_error(regs, 4, trans_exc_code, fault); } -void __kprobes do_dat_exception(struct pt_regs *regs, long error_code) +void __kprobes do_dat_exception(struct pt_regs *regs, long int_code) { - do_exception(regs, error_code & 0xff, 0); + unsigned long trans_exc_code = S390_lowcore.trans_exc_code; + int access, fault; + + access = VM_READ | VM_EXEC | VM_WRITE; +#ifdef CONFIG_S390_EXEC_PROTECT + if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && + (trans_exc_code & 3) == 0) + access = VM_EXEC; +#endif + fault = do_exception(regs, access, trans_exc_code); + if (unlikely(fault)) + do_fault_error(regs, int_code & 255, trans_exc_code, fault); } #ifdef CONFIG_64BIT -void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code) +void __kprobes do_asce_exception(struct pt_regs *regs, long int_code) { - struct mm_struct *mm; + unsigned long trans_exc_code = S390_lowcore.trans_exc_code; + struct mm_struct *mm = current->mm; struct vm_area_struct *vma; - unsigned long address; - int space; - - mm = current->mm; - address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK; - space = check_space(current); - if (unlikely(space == 0 || in_atomic() || !mm)) + if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) goto no_context; local_irq_enable(); down_read(&mm->mmap_sem); - vma = find_vma(mm, address); + vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK); up_read(&mm->mmap_sem); if (vma) { @@ -450,17 +433,38 @@ void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code) /* User mode accesses just cause a SIGSEGV */ if (regs->psw.mask & PSW_MASK_PSTATE) { - current->thread.prot_addr = address; - current->thread.trap_no = error_code; - do_sigsegv(regs, error_code, SEGV_MAPERR, address); + do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code); return; } no_context: - do_no_context(regs, error_code, address); + do_no_context(regs, int_code, trans_exc_code); } #endif +int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user) +{ + struct pt_regs regs; + int access, fault; + + regs.psw.mask = psw_kernel_bits; + if (!irqs_disabled()) + regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; + regs.psw.addr = (unsigned long) __builtin_return_address(0); + regs.psw.addr |= PSW_ADDR_AMODE; + uaddr &= PAGE_MASK; + access = write_user ? VM_WRITE : VM_READ; + fault = do_exception(®s, access, uaddr | 2); + if (unlikely(fault)) { + if (fault & VM_FAULT_OOM) { + pagefault_out_of_memory(); + fault = 0; + } else if (fault & VM_FAULT_SIGBUS) + do_sigbus(®s, int_code, uaddr); + } + return fault ? -EFAULT : 0; +} + #ifdef CONFIG_PFAULT /* * 'pfault' pseudo page faults routines. @@ -522,7 +526,7 @@ void pfault_fini(void) : : "a" (&refbk), "m" (refbk) : "cc"); } -static void pfault_interrupt(__u16 error_code) +static void pfault_interrupt(__u16 int_code) { struct task_struct *tsk; __u16 subcode; diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 2757c5616a07..ad621e06ada3 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -269,7 +269,7 @@ int s390_enable_sie(void) struct mm_struct *mm, *old_mm; /* Do we have switched amode? If no, we cannot do sie */ - if (!switch_amode) + if (user_mode == HOME_SPACE_MODE) return -EINVAL; /* Do we have pgstes? if yes, we are done */ diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 5f91a38d7592..300ab012b0fd 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -70,8 +70,12 @@ static pte_t __ref *vmem_pte_alloc(void) pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t)); if (!pte) return NULL; - clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, - PTRS_PER_PTE * sizeof(pte_t)); + if (MACHINE_HAS_HPAGE) + clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY | _PAGE_CO, + PTRS_PER_PTE * sizeof(pte_t)); + else + clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, + PTRS_PER_PTE * sizeof(pte_t)); return pte; } @@ -112,7 +116,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && (address + HPAGE_SIZE <= start + size) && (address >= HPAGE_SIZE)) { - pte_val(pte) |= _SEGMENT_ENTRY_LARGE; + pte_val(pte) |= _SEGMENT_ENTRY_LARGE | + _SEGMENT_ENTRY_CO; pmd_val(*pm_dir) = pte_val(pte); address += HPAGE_SIZE - PAGE_SIZE; continue; diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 88cdeb9f72d9..0031a6979f3a 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -16,7 +16,9 @@ config SUPERH select HAVE_IOREMAP_PROT if MMU select HAVE_ARCH_TRACEHOOK select HAVE_DMA_API_DEBUG + select HAVE_DMA_ATTRS select HAVE_PERF_EVENTS + select PERF_USE_VMALLOC select HAVE_KERNEL_GZIP select HAVE_KERNEL_BZIP2 select HAVE_KERNEL_LZMA @@ -37,6 +39,7 @@ config SUPERH32 select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACE_MCOUNT_TEST + select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE select HAVE_FUNCTION_GRAPH_TRACER select HAVE_ARCH_KGDB select ARCH_HIBERNATION_POSSIBLE if MMU @@ -170,6 +173,12 @@ config ARCH_HAS_CPU_IDLE_WAIT config IO_TRAPPED bool +config DMA_COHERENT + bool + +config DMA_NONCOHERENT + def_bool !DMA_COHERENT + source "init/Kconfig" source "kernel/Kconfig.freezer" @@ -220,6 +229,7 @@ config CPU_SHX2 config CPU_SHX3 bool + select DMA_COHERENT config ARCH_SHMOBILE bool @@ -761,17 +771,6 @@ config ENTRY_OFFSET default "0x00010000" if PAGE_SIZE_64KB default "0x00000000" -config UBC_WAKEUP - bool "Wakeup UBC on startup" - depends on CPU_SH4 && !CPU_SH4A - help - Selecting this option will wakeup the User Break Controller (UBC) on - startup. Although the UBC is left in an awake state when the processor - comes up, some boot loaders misbehave by putting the UBC to sleep in a - power saving state, which causes issues with things like ptrace(). - - If unsure, say N. - choice prompt "Kernel command line" optional @@ -818,7 +817,13 @@ config MAPLE Dreamcast with a serial line terminal or a remote network connection. -source "arch/sh/drivers/pci/Kconfig" +config PCI + bool "PCI support" + depends on SYS_SUPPORTS_PCI + help + Find out whether you have a PCI motherboard. PCI is the name of a + bus system, i.e. the way the CPU talks to the other stuff inside + your box. If you have PCI, say Y, otherwise N. source "drivers/pci/pcie/Kconfig" diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 66e40aabc600..ac17c5ac550e 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -78,6 +78,9 @@ defaultimage-$(CONFIG_SUPERH32) := zImage defaultimage-$(CONFIG_SH_SH7785LCR) := uImage defaultimage-$(CONFIG_SH_RSK) := uImage defaultimage-$(CONFIG_SH_URQUELL) := uImage +defaultimage-$(CONFIG_SH_MIGOR) := uImage +defaultimage-$(CONFIG_SH_AP325RXA) := uImage +defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE) := uImage defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux @@ -136,6 +139,7 @@ machdir-$(CONFIG_SH_7751_SYSTEMH) += mach-systemh machdir-$(CONFIG_SH_EDOSK7705) += mach-edosk7705 machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander machdir-$(CONFIG_SH_MIGOR) += mach-migor +machdir-$(CONFIG_SH_AP325RXA) += mach-ap325rxa machdir-$(CONFIG_SH_KFR2R09) += mach-kfr2r09 machdir-$(CONFIG_SH_ECOVEC) += mach-ecovec24 machdir-$(CONFIG_SH_SDK7780) += mach-sdk7780 diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index 7baa21090231..ce0f26381784 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -1,7 +1,6 @@ # # Specific board support, not covered by a mach group. # -obj-$(CONFIG_SH_AP325RXA) += board-ap325rxa.o obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o obj-$(CONFIG_SH_URQUELL) += board-urquell.o diff --git a/arch/sh/boards/mach-ap325rxa/Makefile b/arch/sh/boards/mach-ap325rxa/Makefile new file mode 100644 index 000000000000..4cf1774d2613 --- /dev/null +++ b/arch/sh/boards/mach-ap325rxa/Makefile @@ -0,0 +1,2 @@ +obj-y := setup.o sdram.o + diff --git a/arch/sh/boards/mach-ap325rxa/sdram.S b/arch/sh/boards/mach-ap325rxa/sdram.S new file mode 100644 index 000000000000..db24fbed4fca --- /dev/null +++ b/arch/sh/boards/mach-ap325rxa/sdram.S @@ -0,0 +1,69 @@ +/* + * AP325RXA sdram self/auto-refresh setup code + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/sys.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/suspend.h> +#include <asm/romimage-macros.h> + +/* code to enter and leave self-refresh. must be self-contained. + * this code will be copied to on-chip memory and executed from there. + */ + .balign 4 +ENTRY(ap325rxa_sdram_enter_start) + + /* SBSC: disable power down and put in self-refresh mode */ + mov.l 1f, r4 + mov.l 2f, r1 + mov.l @r4, r2 + or r1, r2 + mov.l 3f, r3 + and r3, r2 + mov.l r2, @r4 + + rts + nop + + .balign 4 +1: .long 0xfe400008 /* SDCR0 */ +2: .long 0x00000400 +3: .long 0xffff7fff +ENTRY(ap325rxa_sdram_enter_end) + + .balign 4 +ENTRY(ap325rxa_sdram_leave_start) + + /* SBSC: set auto-refresh mode */ + mov.l 1f, r4 + mov.l @r4, r0 + mov.l 4f, r1 + and r1, r0 + mov.l r0, @r4 + mov.l 6f, r4 + mov.l 8f, r0 + mov.l @r4, r1 + mov #-1, r4 + add r4, r1 + or r1, r0 + mov.l 7f, r1 + mov.l r0, @r1 + + rts + nop + + .balign 4 +1: .long 0xfe400008 /* SDCR0 */ +4: .long 0xfffffbff +6: .long 0xfe40001c /* RTCOR */ +7: .long 0xfe400018 /* RTCNT */ +8: .long 0xa55a0000 +ENTRY(ap325rxa_sdram_leave_end) diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/mach-ap325rxa/setup.c index 2d080732a964..cf9dc12dfeb1 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -20,8 +20,6 @@ #include <linux/i2c.h> #include <linux/smsc911x.h> #include <linux/gpio.h> -#include <linux/spi/spi.h> -#include <linux/spi/spi_gpio.h> #include <media/ov772x.h> #include <media/soc_camera.h> #include <media/soc_camera_platform.h> @@ -29,6 +27,7 @@ #include <video/sh_mobile_lcdc.h> #include <asm/io.h> #include <asm/clock.h> +#include <asm/suspend.h> #include <cpu/sh7723.h> static struct smsc911x_platform_config smsc911x_config = { @@ -409,17 +408,49 @@ static struct platform_device ceu_device = { }, }; -struct spi_gpio_platform_data sdcard_cn3_platform_data = { - .sck = GPIO_PTD0, - .mosi = GPIO_PTD1, - .miso = GPIO_PTD2, - .num_chipselect = 1, +static struct resource sdhi0_cn3_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, }; -static struct platform_device sdcard_cn3_device = { - .name = "spi_gpio", - .dev = { - .platform_data = &sdcard_cn3_platform_data, +static struct platform_device sdhi0_cn3_device = { + .name = "sh_mobile_sdhi", + .id = 0, /* "sdhi0" clock */ + .num_resources = ARRAY_SIZE(sdhi0_cn3_resources), + .resource = sdhi0_cn3_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + +static struct resource sdhi1_cn7_resources[] = { + [0] = { + .name = "SDHI1", + .start = 0x04cf0000, + .end = 0x04cf01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 24, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi1_cn7_device = { + .name = "sh_mobile_sdhi", + .id = 1, /* "sdhi1" clock */ + .num_resources = ARRAY_SIZE(sdhi1_cn7_resources), + .resource = sdhi1_cn7_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI1, }, }; @@ -470,22 +501,26 @@ static struct platform_device *ap325rxa_devices[] __initdata = { &lcdc_device, &ceu_device, &nand_flash_device, - &sdcard_cn3_device, + &sdhi0_cn3_device, + &sdhi1_cn7_device, &ap325rxa_camera[0], &ap325rxa_camera[1], }; -static struct spi_board_info ap325rxa_spi_devices[] = { - { - .modalias = "mmc_spi", - .max_speed_hz = 5000000, - .chip_select = 0, - .controller_data = (void *) GPIO_PTD5, - }, -}; +extern char ap325rxa_sdram_enter_start; +extern char ap325rxa_sdram_enter_end; +extern char ap325rxa_sdram_leave_start; +extern char ap325rxa_sdram_leave_end; static int __init ap325rxa_devices_setup(void) { + /* register board specific self-refresh code */ + sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF, + &ap325rxa_sdram_enter_start, + &ap325rxa_sdram_enter_end, + &ap325rxa_sdram_leave_start, + &ap325rxa_sdram_leave_end); + /* LD3 and LD4 LEDs */ gpio_request(GPIO_PTX5, NULL); /* RUN */ gpio_direction_output(GPIO_PTX5, 1); @@ -578,12 +613,28 @@ static int __init ap325rxa_devices_setup(void) platform_resource_setup_memory(&ceu_device, "ceu", 4 << 20); + /* SDHI0 - CN3 - SD CARD */ + gpio_request(GPIO_FN_SDHI0CD_PTD, NULL); + gpio_request(GPIO_FN_SDHI0WP_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D3_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D2_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D1_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D0_PTD, NULL); + gpio_request(GPIO_FN_SDHI0CMD_PTD, NULL); + gpio_request(GPIO_FN_SDHI0CLK_PTD, NULL); + + /* SDHI1 - CN7 - MICRO SD CARD */ + gpio_request(GPIO_FN_SDHI1CD, NULL); + gpio_request(GPIO_FN_SDHI1D3, NULL); + gpio_request(GPIO_FN_SDHI1D2, NULL); + gpio_request(GPIO_FN_SDHI1D1, NULL); + gpio_request(GPIO_FN_SDHI1D0, NULL); + gpio_request(GPIO_FN_SDHI1CMD, NULL); + gpio_request(GPIO_FN_SDHI1CLK, NULL); + i2c_register_board_info(0, ap325rxa_i2c_devices, ARRAY_SIZE(ap325rxa_i2c_devices)); - spi_register_board_info(ap325rxa_spi_devices, - ARRAY_SIZE(ap325rxa_spi_devices)); - return platform_add_devices(ap325rxa_devices, ARRAY_SIZE(ap325rxa_devices)); } diff --git a/arch/sh/boards/mach-ecovec24/Makefile b/arch/sh/boards/mach-ecovec24/Makefile index 51f852151655..e69bc82208fc 100644 --- a/arch/sh/boards/mach-ecovec24/Makefile +++ b/arch/sh/boards/mach-ecovec24/Makefile @@ -6,4 +6,4 @@ # for more details. # -obj-y := setup.o
\ No newline at end of file +obj-y := setup.o sdram.o
\ No newline at end of file diff --git a/arch/sh/boards/mach-ecovec24/sdram.S b/arch/sh/boards/mach-ecovec24/sdram.S new file mode 100644 index 000000000000..833440044407 --- /dev/null +++ b/arch/sh/boards/mach-ecovec24/sdram.S @@ -0,0 +1,52 @@ +/* + * Ecovec24 sdram self/auto-refresh setup code + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/sys.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/suspend.h> +#include <asm/romimage-macros.h> + +/* code to enter and leave self-refresh. must be self-contained. + * this code will be copied to on-chip memory and executed from there. + */ + .balign 4 +ENTRY(ecovec24_sdram_enter_start) + + /* DBSC: put memory in self-refresh mode */ + + ED 0xFD000010, 0x00000000 /* DBEN */ + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000040, 0x00000001 /* DBRFPDN0 */ + + rts + nop + +ENTRY(ecovec24_sdram_enter_end) + + .balign 4 +ENTRY(ecovec24_sdram_leave_start) + + /* DBSC: put memory in auto-refresh mode */ + + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + WAIT 1 + ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000010, 0x00000001 /* DBEN */ + ED 0xFD000040, 0x00010000 /* DBRFPDN0 */ + + rts + nop + +ENTRY(ecovec24_sdram_leave_end) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3b1ceb46fa54..826e62326d51 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -20,12 +20,14 @@ #include <linux/i2c.h> #include <linux/i2c/tsc2007.h> #include <linux/input.h> +#include <linux/input/sh_keysc.h> +#include <linux/mfd/sh_mobile_sdhi.h> #include <video/sh_mobile_lcdc.h> #include <media/sh_mobile_ceu.h> #include <asm/heartbeat.h> #include <asm/sh_eth.h> -#include <asm/sh_keysc.h> #include <asm/clock.h> +#include <asm/suspend.h> #include <cpu/sh7724.h> /* @@ -147,6 +149,9 @@ static struct platform_device sh_eth_device = { }, .num_resources = ARRAY_SIZE(sh_eth_resources), .resource = sh_eth_resources, + .archdata = { + .hwblk_id = HWBLK_ETHER, + }, }; /* USB0 host */ @@ -185,30 +190,18 @@ static struct platform_device usb0_host_device = { .resource = usb0_host_resources, }; -/* - * USB1 - * - * CN5 can use both host/function, - * and we can determine it by checking PTB[3] - * - * This time only USB1 host is supported. - */ +/* USB1 host/function */ void usb1_port_power(int port, int power) { - if (!gpio_get_value(GPIO_PTB3)) { - printk(KERN_ERR "USB1 function is not supported\n"); - return; - } - gpio_set_value(GPIO_PTB5, power); } -static struct r8a66597_platdata usb1_host_data = { +static struct r8a66597_platdata usb1_common_data = { .on_chip = 1, .port_power = usb1_port_power, }; -static struct resource usb1_host_resources[] = { +static struct resource usb1_common_resources[] = { [0] = { .start = 0xa4d90000, .end = 0xa4d90124 - 1, @@ -221,16 +214,16 @@ static struct resource usb1_host_resources[] = { }, }; -static struct platform_device usb1_host_device = { - .name = "r8a66597_hcd", +static struct platform_device usb1_common_device = { + /* .name will be added in arch_setup */ .id = 1, .dev = { .dma_mask = NULL, /* not use dma */ .coherent_dma_mask = 0xffffffff, - .platform_data = &usb1_host_data, + .platform_data = &usb1_common_data, }, - .num_resources = ARRAY_SIZE(usb1_host_resources), - .resource = usb1_host_resources, + .num_resources = ARRAY_SIZE(usb1_common_resources), + .resource = usb1_common_resources, }; /* LCDC */ @@ -428,16 +421,90 @@ static struct i2c_board_info ts_i2c_clients = { .irq = IRQ0, }; +/* SHDI0 */ +static void sdhi0_set_pwr(struct platform_device *pdev, int state) +{ + gpio_set_value(GPIO_PTB6, state); +} + +static struct sh_mobile_sdhi_info sdhi0_info = { + .set_pwr = sdhi0_set_pwr, +}; + +static struct resource sdhi0_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi0_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi0_resources), + .resource = sdhi0_resources, + .id = 0, + .dev = { + .platform_data = &sdhi0_info, + }, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + +/* SHDI1 */ +static void sdhi1_set_pwr(struct platform_device *pdev, int state) +{ + gpio_set_value(GPIO_PTB7, state); +} + +static struct sh_mobile_sdhi_info sdhi1_info = { + .set_pwr = sdhi1_set_pwr, +}; + +static struct resource sdhi1_resources[] = { + [0] = { + .name = "SDHI1", + .start = 0x04cf0000, + .end = 0x04cf01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 24, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi1_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi1_resources), + .resource = sdhi1_resources, + .id = 1, + .dev = { + .platform_data = &sdhi1_info, + }, + .archdata = { + .hwblk_id = HWBLK_SDHI1, + }, +}; + static struct platform_device *ecovec_devices[] __initdata = { &heartbeat_device, &nor_flash_device, &sh_eth_device, &usb0_host_device, - &usb1_host_device, /* USB1 host support */ + &usb1_common_device, &lcdc_device, &ceu0_device, &ceu1_device, &keysc_device, + &sdhi0_device, + &sdhi1_device, }; #define EEPROM_ADDR 0x50 @@ -466,12 +533,9 @@ static u8 mac_read(struct i2c_adapter *a, u8 command) return buf; } -#define MAC_LEN 6 -static void __init sh_eth_init(void) +static void __init sh_eth_init(struct sh_eth_plat_data *pd) { struct i2c_adapter *a = i2c_get_adapter(1); - struct clk *eth_clk; - u8 mac[MAC_LEN]; int i; if (!a) { @@ -479,39 +543,30 @@ static void __init sh_eth_init(void) return; } - eth_clk = clk_get(NULL, "eth0"); - if (!eth_clk) { - pr_err("can not get eth0 clk\n"); - return; - } - /* read MAC address frome EEPROM */ - for (i = 0; i < MAC_LEN; i++) { - mac[i] = mac_read(a, 0x10 + i); + for (i = 0; i < sizeof(pd->mac_addr); i++) { + pd->mac_addr[i] = mac_read(a, 0x10 + i); msleep(10); } - - /* clock enable */ - clk_enable(eth_clk); - - /* reset sh-eth */ - ctrl_outl(0x1, SH_ETH_ADDR + 0x0); - - /* set MAC addr */ - ctrl_outl((mac[0] << 24) | - (mac[1] << 16) | - (mac[2] << 8) | - (mac[3] << 0), SH_ETH_MAHR); - ctrl_outl((mac[4] << 8) | - (mac[5] << 0), SH_ETH_MALR); - - clk_put(eth_clk); } #define PORT_HIZA 0xA4050158 #define IODRIVEA 0xA405018A + +extern char ecovec24_sdram_enter_start; +extern char ecovec24_sdram_enter_end; +extern char ecovec24_sdram_leave_start; +extern char ecovec24_sdram_leave_end; + static int __init arch_setup(void) { + /* register board specific self-refresh code */ + sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF, + &ecovec24_sdram_enter_start, + &ecovec24_sdram_enter_end, + &ecovec24_sdram_leave_start, + &ecovec24_sdram_leave_end); + /* enable STATUS0, STATUS2 and PDSTATUS */ gpio_request(GPIO_FN_STATUS0, NULL); gpio_request(GPIO_FN_STATUS2, NULL); @@ -561,6 +616,14 @@ static int __init arch_setup(void) ctrl_outw(0x0600, 0xa40501d4); ctrl_outw(0x0600, 0xa4050192); + if (gpio_get_value(GPIO_PTB3)) { + printk(KERN_INFO "USB1 function is selected\n"); + usb1_common_device.name = "r8a66597_udc"; + } else { + printk(KERN_INFO "USB1 host is selected\n"); + usb1_common_device.name = "r8a66597_hcd"; + } + /* enable LCDC */ gpio_request(GPIO_FN_LCDD23, NULL); gpio_request(GPIO_FN_LCDD22, NULL); @@ -603,8 +666,8 @@ static int __init arch_setup(void) gpio_direction_output(GPIO_PTR1, 0); gpio_direction_output(GPIO_PTA2, 0); - /* I/O buffer drive ability is low */ - ctrl_outw((ctrl_inw(IODRIVEA) & ~0x00c0) | 0x0040 , IODRIVEA); + /* I/O buffer drive ability is high */ + ctrl_outw((ctrl_inw(IODRIVEA) & ~0x00c0) | 0x0080 , IODRIVEA); if (gpio_get_value(GPIO_PTE6)) { /* DVI */ @@ -710,6 +773,33 @@ static int __init arch_setup(void) gpio_direction_input(GPIO_PTR5); gpio_direction_input(GPIO_PTR6); + /* enable SDHI0 (needs DS2.4 set to ON) */ + gpio_request(GPIO_FN_SDHI0CD, NULL); + gpio_request(GPIO_FN_SDHI0WP, NULL); + gpio_request(GPIO_FN_SDHI0CMD, NULL); + gpio_request(GPIO_FN_SDHI0CLK, NULL); + gpio_request(GPIO_FN_SDHI0D3, NULL); + gpio_request(GPIO_FN_SDHI0D2, NULL); + gpio_request(GPIO_FN_SDHI0D1, NULL); + gpio_request(GPIO_FN_SDHI0D0, NULL); + gpio_request(GPIO_PTB6, NULL); + gpio_direction_output(GPIO_PTB6, 0); + + /* enable SDHI1 (needs DS2.6,7 set to ON,OFF) */ + gpio_request(GPIO_FN_SDHI1CD, NULL); + gpio_request(GPIO_FN_SDHI1WP, NULL); + gpio_request(GPIO_FN_SDHI1CMD, NULL); + gpio_request(GPIO_FN_SDHI1CLK, NULL); + gpio_request(GPIO_FN_SDHI1D3, NULL); + gpio_request(GPIO_FN_SDHI1D2, NULL); + gpio_request(GPIO_FN_SDHI1D1, NULL); + gpio_request(GPIO_FN_SDHI1D0, NULL); + gpio_request(GPIO_PTB7, NULL); + gpio_direction_output(GPIO_PTB7, 0); + + /* I/O buffer drive ability is high for SDHI1 */ + ctrl_outw((ctrl_inw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA); + /* enable I2C device */ i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); @@ -721,12 +811,11 @@ arch_initcall(arch_setup); static int __init devices_setup(void) { - sh_eth_init(); + sh_eth_init(&sh_eth_plat); return 0; } device_initcall(devices_setup); - static struct sh_machine_vector mv_ecovec __initmv = { .mv_name = "R0P7724 (EcoVec)", }; diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c index 566e69d8d729..f663c14d8885 100644 --- a/arch/sh/boards/mach-highlander/setup.c +++ b/arch/sh/boards/mach-highlander/setup.c @@ -384,7 +384,7 @@ static unsigned char irl2irq[HL_NR_IRL]; static int highlander_irq_demux(int irq) { - if (irq >= HL_NR_IRL || !irl2irq[irq]) + if (irq >= HL_NR_IRL || irq < 0 || !irl2irq[irq]) return irq; return irl2irq[irq]; diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile index 5d5867826e3b..4e577a3bf658 100644 --- a/arch/sh/boards/mach-kfr2r09/Makefile +++ b/arch/sh/boards/mach-kfr2r09/Makefile @@ -1,2 +1,2 @@ -obj-y := setup.o +obj-y := setup.o sdram.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += lcd_wqvga.o diff --git a/arch/sh/boards/mach-kfr2r09/sdram.S b/arch/sh/boards/mach-kfr2r09/sdram.S new file mode 100644 index 000000000000..0c9f55bec2fe --- /dev/null +++ b/arch/sh/boards/mach-kfr2r09/sdram.S @@ -0,0 +1,80 @@ +/* + * KFR2R09 sdram self/auto-refresh setup code + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/sys.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/suspend.h> +#include <asm/romimage-macros.h> + +/* code to enter and leave self-refresh. must be self-contained. + * this code will be copied to on-chip memory and executed from there. + */ + .balign 4 +ENTRY(kfr2r09_sdram_enter_start) + + /* DBSC: put memory in self-refresh mode */ + + ED 0xFD000010, 0x00000000 /* DBEN */ + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000040, 0x00000001 /* DBRFPDN0 */ + + rts + nop + +ENTRY(kfr2r09_sdram_enter_end) + + .balign 4 +ENTRY(kfr2r09_sdram_leave_start) + + /* DBSC: put memory in auto-refresh mode */ + + mov.l @(SH_SLEEP_MODE, r5), r0 + tst #SUSP_SH_RSTANDBY, r0 + bf resume_rstandby + + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + WAIT 1 + ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000010, 0x00000001 /* DBEN */ + ED 0xFD000040, 0x00010000 /* DBRFPDN0 */ + + rts + nop + +resume_rstandby: + + /* DBSC: re-initialize and put in auto-refresh */ + + ED 0xFD000108, 0x40000301 /* DBPDCNT0 */ + ED 0xFD000020, 0x011B0002 /* DBCONF */ + ED 0xFD000030, 0x03060E02 /* DBTR0 */ + ED 0xFD000034, 0x01020102 /* DBTR1 */ + ED 0xFD000038, 0x01090406 /* DBTR2 */ + ED 0xFD000008, 0x00000004 /* DBKIND */ + ED 0xFD000040, 0x00000001 /* DBRFPDN0 */ + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + ED 0xFD000018, 0x00000001 /* DBCKECNT */ + WAIT 1 + ED 0xFD000010, 0x00000001 /* DBEN */ + ED 0xFD000044, 0x000004AF /* DBRFPDN1 */ + ED 0xFD000048, 0x20CF0037 /* DBRFPDN2 */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000108, 0x40000300 /* DBPDCNT0 */ + ED 0xFD000040, 0x00010000 /* DBRFPDN0 */ + + rts + nop + +ENTRY(kfr2r09_sdram_leave_end) diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index c08d33fe2104..87438d6603d6 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -16,13 +16,16 @@ #include <linux/clk.h> #include <linux/gpio.h> #include <linux/input.h> +#include <linux/input/sh_keysc.h> #include <linux/i2c.h> #include <linux/usb/r8a66597.h> +#include <media/soc_camera.h> +#include <media/sh_mobile_ceu.h> #include <video/sh_mobile_lcdc.h> +#include <asm/suspend.h> #include <asm/clock.h> #include <asm/machvec.h> #include <asm/io.h> -#include <asm/sh_keysc.h> #include <cpu/sh7724.h> #include <mach/kfr2r09.h> @@ -212,11 +215,154 @@ static struct platform_device kfr2r09_usb0_gadget_device = { .resource = kfr2r09_usb0_gadget_resources, }; +static struct sh_mobile_ceu_info sh_mobile_ceu_info = { + .flags = SH_CEU_FLAG_USE_8BIT_BUS, +}; + +static struct resource kfr2r09_ceu_resources[] = { + [0] = { + .name = "CEU", + .start = 0xfe910000, + .end = 0xfe91009f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 52, + .end = 52, + .flags = IORESOURCE_IRQ, + }, + [2] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device kfr2r09_ceu_device = { + .name = "sh_mobile_ceu", + .id = 0, /* "ceu0" clock */ + .num_resources = ARRAY_SIZE(kfr2r09_ceu_resources), + .resource = kfr2r09_ceu_resources, + .dev = { + .platform_data = &sh_mobile_ceu_info, + }, + .archdata = { + .hwblk_id = HWBLK_CEU0, + }, +}; + +static struct i2c_board_info kfr2r09_i2c_camera = { + I2C_BOARD_INFO("rj54n1cb0c", 0x50), +}; + +static struct clk *camera_clk; + +#define DRVCRB 0xA405018C +static int camera_power(struct device *dev, int mode) +{ + int ret; + + if (mode) { + long rate; + + camera_clk = clk_get(NULL, "video_clk"); + if (IS_ERR(camera_clk)) + return PTR_ERR(camera_clk); + + /* set VIO_CKO clock to 25MHz */ + rate = clk_round_rate(camera_clk, 25000000); + ret = clk_set_rate(camera_clk, rate); + if (ret < 0) + goto eclkrate; + + /* set DRVCRB + * + * use 1.8 V for VccQ_VIO + * use 2.85V for VccQ_SR + */ + ctrl_outw((ctrl_inw(DRVCRB) & ~0x0003) | 0x0001, DRVCRB); + + /* reset clear */ + ret = gpio_request(GPIO_PTB4, NULL); + if (ret < 0) + goto eptb4; + ret = gpio_request(GPIO_PTB7, NULL); + if (ret < 0) + goto eptb7; + + ret = gpio_direction_output(GPIO_PTB4, 1); + if (!ret) + ret = gpio_direction_output(GPIO_PTB7, 1); + if (ret < 0) + goto egpioout; + msleep(1); + + ret = clk_enable(camera_clk); /* start VIO_CKO */ + if (ret < 0) + goto eclkon; + + return 0; + } + + ret = 0; + + clk_disable(camera_clk); +eclkon: + gpio_set_value(GPIO_PTB7, 0); +egpioout: + gpio_set_value(GPIO_PTB4, 0); + gpio_free(GPIO_PTB7); +eptb7: + gpio_free(GPIO_PTB4); +eptb4: +eclkrate: + clk_put(camera_clk); + return ret; +} + +static struct soc_camera_link rj54n1_link = { + .power = camera_power, + .board_info = &kfr2r09_i2c_camera, + .i2c_adapter_id = 1, + .module_name = "rj54n1cb0c", +}; + +static struct platform_device kfr2r09_camera = { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &rj54n1_link, + }, +}; + +static struct resource kfr2r09_sh_sdhi0_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device kfr2r09_sh_sdhi0_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(kfr2r09_sh_sdhi0_resources), + .resource = kfr2r09_sh_sdhi0_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + static struct platform_device *kfr2r09_devices[] __initdata = { &kfr2r09_nor_flash_device, &kfr2r09_nand_flash_device, &kfr2r09_sh_keysc_device, &kfr2r09_sh_lcdc_device, + &kfr2r09_ceu_device, + &kfr2r09_camera, + &kfr2r09_sh_sdhi0_device, }; #define BSC_CS0BCR 0xfec10004 @@ -268,11 +414,59 @@ static int kfr2r09_usb0_gadget_i2c_setup(void) return 0; } + +static int kfr2r09_serial_i2c_setup(void) +{ + struct i2c_adapter *a; + struct i2c_msg msg; + unsigned char buf[2]; + int ret; + + a = i2c_get_adapter(0); + if (!a) + return -ENODEV; + + /* set bit 6 (the 7th bit) of chip at 0x09, register 0x13 */ + buf[0] = 0x13; + msg.addr = 0x09; + msg.buf = buf; + msg.len = 1; + msg.flags = 0; + ret = i2c_transfer(a, &msg, 1); + if (ret != 1) + return -ENODEV; + + buf[0] = 0; + msg.addr = 0x09; + msg.buf = buf; + msg.len = 1; + msg.flags = I2C_M_RD; + ret = i2c_transfer(a, &msg, 1); + if (ret != 1) + return -ENODEV; + + buf[1] = buf[0] | (1 << 6); + buf[0] = 0x13; + msg.addr = 0x09; + msg.buf = buf; + msg.len = 2; + msg.flags = 0; + ret = i2c_transfer(a, &msg, 1); + if (ret != 1) + return -ENODEV; + + return 0; +} #else static int kfr2r09_usb0_gadget_i2c_setup(void) { return -ENODEV; } + +static int kfr2r09_serial_i2c_setup(void) +{ + return -ENODEV; +} #endif static int kfr2r09_usb0_gadget_setup(void) @@ -299,11 +493,27 @@ static int kfr2r09_usb0_gadget_setup(void) return 0; } +extern char kfr2r09_sdram_enter_start; +extern char kfr2r09_sdram_enter_end; +extern char kfr2r09_sdram_leave_start; +extern char kfr2r09_sdram_leave_end; + static int __init kfr2r09_devices_setup(void) { + /* register board specific self-refresh code */ + sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF | + SUSP_SH_RSTANDBY, + &kfr2r09_sdram_enter_start, + &kfr2r09_sdram_enter_end, + &kfr2r09_sdram_leave_start, + &kfr2r09_sdram_leave_end); + /* enable SCIF1 serial port for YC401 console support */ gpio_request(GPIO_FN_SCIF1_RXD, NULL); gpio_request(GPIO_FN_SCIF1_TXD, NULL); + kfr2r09_serial_i2c_setup(); /* ECONTMSK(bit6=L10ONEN) set 1 */ + gpio_request(GPIO_PTG3, NULL); /* HPON_ON */ + gpio_direction_output(GPIO_PTG3, 1); /* HPON_ON = H */ /* setup NOR flash at CS0 */ ctrl_outl(0x36db0400, BSC_CS0BCR); @@ -361,6 +571,32 @@ static int __init kfr2r09_devices_setup(void) if (kfr2r09_usb0_gadget_setup() == 0) platform_device_register(&kfr2r09_usb0_gadget_device); + /* CEU */ + gpio_request(GPIO_FN_VIO_CKO, NULL); + gpio_request(GPIO_FN_VIO0_CLK, NULL); + gpio_request(GPIO_FN_VIO0_VD, NULL); + gpio_request(GPIO_FN_VIO0_HD, NULL); + gpio_request(GPIO_FN_VIO0_FLD, NULL); + gpio_request(GPIO_FN_VIO0_D7, NULL); + gpio_request(GPIO_FN_VIO0_D6, NULL); + gpio_request(GPIO_FN_VIO0_D5, NULL); + gpio_request(GPIO_FN_VIO0_D4, NULL); + gpio_request(GPIO_FN_VIO0_D3, NULL); + gpio_request(GPIO_FN_VIO0_D2, NULL); + gpio_request(GPIO_FN_VIO0_D1, NULL); + gpio_request(GPIO_FN_VIO0_D0, NULL); + + platform_resource_setup_memory(&kfr2r09_ceu_device, "ceu", 4 << 20); + + /* SDHI0 connected to yc304 */ + gpio_request(GPIO_FN_SDHI0CD, NULL); + gpio_request(GPIO_FN_SDHI0D3, NULL); + gpio_request(GPIO_FN_SDHI0D2, NULL); + gpio_request(GPIO_FN_SDHI0D1, NULL); + gpio_request(GPIO_FN_SDHI0D0, NULL); + gpio_request(GPIO_FN_SDHI0CMD, NULL); + gpio_request(GPIO_FN_SDHI0CLK, NULL); + return platform_add_devices(kfr2r09_devices, ARRAY_SIZE(kfr2r09_devices)); } diff --git a/arch/sh/boards/mach-migor/Makefile b/arch/sh/boards/mach-migor/Makefile index 5f231dd25c0e..4601a89e5ac7 100644 --- a/arch/sh/boards/mach-migor/Makefile +++ b/arch/sh/boards/mach-migor/Makefile @@ -1,2 +1,2 @@ -obj-y := setup.o +obj-y := setup.o sdram.o obj-$(CONFIG_SH_MIGOR_QVGA) += lcd_qvga.o diff --git a/arch/sh/boards/mach-migor/sdram.S b/arch/sh/boards/mach-migor/sdram.S new file mode 100644 index 000000000000..614aa3a1398c --- /dev/null +++ b/arch/sh/boards/mach-migor/sdram.S @@ -0,0 +1,69 @@ +/* + * Migo-R sdram self/auto-refresh setup code + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/sys.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/suspend.h> +#include <asm/romimage-macros.h> + +/* code to enter and leave self-refresh. must be self-contained. + * this code will be copied to on-chip memory and executed from there. + */ + .balign 4 +ENTRY(migor_sdram_enter_start) + + /* SBSC: disable power down and put in self-refresh mode */ + mov.l 1f, r4 + mov.l 2f, r1 + mov.l @r4, r2 + or r1, r2 + mov.l 3f, r3 + and r3, r2 + mov.l r2, @r4 + + rts + nop + + .balign 4 +1: .long 0xfe400008 /* SDCR0 */ +2: .long 0x00000400 +3: .long 0xffff7fff +ENTRY(migor_sdram_enter_end) + + .balign 4 +ENTRY(migor_sdram_leave_start) + + /* SBSC: set auto-refresh mode */ + mov.l 1f, r4 + mov.l @r4, r0 + mov.l 4f, r1 + and r1, r0 + mov.l r0, @r4 + mov.l 6f, r4 + mov.l 8f, r0 + mov.l @r4, r1 + mov #-1, r4 + add r4, r1 + or r1, r0 + mov.l 7f, r1 + mov.l r0, @r1 + + rts + nop + + .balign 4 +1: .long 0xfe400008 /* SDCR0 */ +4: .long 0xfffffbff +6: .long 0xfe40001c /* RTCOR */ +7: .long 0xfe400018 /* RTCNT */ +8: .long 0xa55a0000 +ENTRY(migor_sdram_leave_end) diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 6ed1fd32369e..9099b6da9957 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -11,6 +11,7 @@ #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/input.h> +#include <linux/input/sh_keysc.h> #include <linux/mtd/physmap.h> #include <linux/mtd/nand.h> #include <linux/i2c.h> @@ -18,8 +19,6 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/gpio.h> -#include <linux/spi/spi.h> -#include <linux/spi/spi_gpio.h> #include <video/sh_mobile_lcdc.h> #include <media/sh_mobile_ceu.h> #include <media/ov772x.h> @@ -27,7 +26,7 @@ #include <asm/clock.h> #include <asm/machvec.h> #include <asm/io.h> -#include <asm/sh_keysc.h> +#include <asm/suspend.h> #include <mach/migor.h> #include <cpu/sh7722.h> @@ -390,17 +389,25 @@ static struct platform_device migor_ceu_device = { }, }; -struct spi_gpio_platform_data sdcard_cn9_platform_data = { - .sck = GPIO_PTD0, - .mosi = GPIO_PTD1, - .miso = GPIO_PTD2, - .num_chipselect = 1, +static struct resource sdhi_cn9_resources[] = { + [0] = { + .name = "SDHI", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, }; -static struct platform_device sdcard_cn9_device = { - .name = "spi_gpio", - .dev = { - .platform_data = &sdcard_cn9_platform_data, +static struct platform_device sdhi_cn9_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi_cn9_resources), + .resource = sdhi_cn9_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI, }, }; @@ -467,23 +474,24 @@ static struct platform_device *migor_devices[] __initdata = { &migor_ceu_device, &migor_nor_flash_device, &migor_nand_flash_device, - &sdcard_cn9_device, + &sdhi_cn9_device, &migor_camera[0], &migor_camera[1], }; -static struct spi_board_info migor_spi_devices[] = { - { - .modalias = "mmc_spi", - .max_speed_hz = 5000000, - .chip_select = 0, - .controller_data = (void *) GPIO_PTD5, - }, -}; +extern char migor_sdram_enter_start; +extern char migor_sdram_enter_end; +extern char migor_sdram_leave_start; +extern char migor_sdram_leave_end; static int __init migor_devices_setup(void) { - + /* register board specific self-refresh code */ + sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF, + &migor_sdram_enter_start, + &migor_sdram_enter_end, + &migor_sdram_leave_start, + &migor_sdram_leave_end); #ifdef CONFIG_PM /* Let D11 LED show STATUS0 */ gpio_request(GPIO_FN_STATUS0, NULL); @@ -525,6 +533,16 @@ static int __init migor_devices_setup(void) gpio_request(GPIO_PTA1, NULL); gpio_direction_input(GPIO_PTA1); + /* SDHI */ + gpio_request(GPIO_FN_SDHICD, NULL); + gpio_request(GPIO_FN_SDHIWP, NULL); + gpio_request(GPIO_FN_SDHID3, NULL); + gpio_request(GPIO_FN_SDHID2, NULL); + gpio_request(GPIO_FN_SDHID1, NULL); + gpio_request(GPIO_FN_SDHID0, NULL); + gpio_request(GPIO_FN_SDHICMD, NULL); + gpio_request(GPIO_FN_SDHICLK, NULL); + /* Touch Panel */ gpio_request(GPIO_FN_IRQ6, NULL); @@ -612,9 +630,6 @@ static int __init migor_devices_setup(void) i2c_register_board_info(0, migor_i2c_devices, ARRAY_SIZE(migor_i2c_devices)); - spi_register_board_info(migor_spi_devices, - ARRAY_SIZE(migor_spi_devices)); - return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices)); } arch_initcall(migor_devices_setup); diff --git a/arch/sh/boards/mach-r2d/irq.c b/arch/sh/boards/mach-r2d/irq.c index c70fecedcac4..78d7b27c80da 100644 --- a/arch/sh/boards/mach-r2d/irq.c +++ b/arch/sh/boards/mach-r2d/irq.c @@ -116,7 +116,7 @@ static unsigned char irl2irq[R2D_NR_IRL]; int rts7751r2d_irq_demux(int irq) { - if (irq >= R2D_NR_IRL || !irl2irq[irq]) + if (irq >= R2D_NR_IRL || irq < 0 || !irl2irq[irq]) return irq; return irl2irq[irq]; diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c index 02d21a3e2a8f..4eb31acfafef 100644 --- a/arch/sh/boards/mach-se/7722/irq.c +++ b/arch/sh/boards/mach-se/7722/irq.c @@ -16,15 +16,17 @@ #include <asm/io.h> #include <mach-se/mach/se7722.h> +unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, }; + static void disable_se7722_irq(unsigned int irq) { - unsigned int bit = irq - SE7722_FPGA_IRQ_BASE; + unsigned int bit = (unsigned int)get_irq_chip_data(irq); ctrl_outw(ctrl_inw(IRQ01_MASK) | 1 << bit, IRQ01_MASK); } static void enable_se7722_irq(unsigned int irq) { - unsigned int bit = irq - SE7722_FPGA_IRQ_BASE; + unsigned int bit = (unsigned int)get_irq_chip_data(irq); ctrl_outw(ctrl_inw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK); } @@ -38,18 +40,15 @@ static struct irq_chip se7722_irq_chip __read_mostly = { static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) { unsigned short intv = ctrl_inw(IRQ01_STS); - struct irq_desc *ext_desc; - unsigned int ext_irq = SE7722_FPGA_IRQ_BASE; + unsigned int ext_irq = 0; intv &= (1 << SE7722_FPGA_IRQ_NR) - 1; - while (intv) { - if (intv & 1) { - ext_desc = irq_desc + ext_irq; - handle_level_irq(ext_irq, ext_desc); - } - intv >>= 1; - ext_irq++; + for (; intv; intv >>= 1, ext_irq++) { + if (!(intv & 1)) + continue; + + generic_handle_irq(se7722_fpga_irq[ext_irq]); } } @@ -63,11 +62,18 @@ void __init init_se7722_IRQ(void) ctrl_outw(0, IRQ01_MASK); /* disable all irqs */ ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */ - for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) - set_irq_chip_and_handler_name(SE7722_FPGA_IRQ_BASE + i, + for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { + se7722_fpga_irq[i] = create_irq(); + if (se7722_fpga_irq[i] < 0) + return; + + set_irq_chip_and_handler_name(se7722_fpga_irq[i], &se7722_irq_chip, handle_level_irq, "level"); + set_irq_chip_data(se7722_fpga_irq[i], (void *)i); + } + set_irq_chained_handler(IRQ0_IRQ, se7722_irq_demux); set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c index 36374078e521..b1cb9425b600 100644 --- a/arch/sh/boards/mach-se/7722/setup.c +++ b/arch/sh/boards/mach-se/7722/setup.c @@ -14,6 +14,7 @@ #include <linux/platform_device.h> #include <linux/ata_platform.h> #include <linux/input.h> +#include <linux/input/sh_keysc.h> #include <linux/smc91x.h> #include <mach-se/mach/se7722.h> #include <mach-se/mach/mrshpc.h> @@ -21,7 +22,6 @@ #include <asm/clock.h> #include <asm/io.h> #include <asm/heartbeat.h> -#include <asm/sh_keysc.h> #include <cpu/sh7722.h> /* Heartbeat */ @@ -60,8 +60,7 @@ static struct resource smc91x_eth_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = SMC_IRQ, - .end = SMC_IRQ, + /* Filled in later */ .flags = IORESOURCE_IRQ, }, }; @@ -90,8 +89,7 @@ static struct resource cf_ide_resources[] = { .flags = IORESOURCE_IO, }, [2] = { - .start = MRSHPC_IRQ0, - .end = MRSHPC_IRQ0, + /* Filled in later */ .flags = IORESOURCE_IRQ, }, }; @@ -153,6 +151,14 @@ static struct platform_device *se7722_devices[] __initdata = { static int __init se7722_devices_setup(void) { mrshpc_setup_windows(); + + /* Wire-up dynamic vectors */ + cf_ide_resources[2].start = cf_ide_resources[2].end = + se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0]; + + smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = + se7722_fpga_irq[SE7722_FPGA_IRQ_SMC]; + return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices)); } device_initcall(se7722_devices_setup); @@ -193,6 +199,5 @@ static void __init se7722_setup(char **cmdline_p) static struct sh_machine_vector mv_se7722 __initmv = { .mv_name = "Solution Engine 7722" , .mv_setup = se7722_setup , - .mv_nr_irqs = SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_NR, .mv_init_irq = init_se7722_IRQ, }; diff --git a/arch/sh/boards/mach-se/7724/Makefile b/arch/sh/boards/mach-se/7724/Makefile index 349cbd6ce82d..a08b36830f0e 100644 --- a/arch/sh/boards/mach-se/7724/Makefile +++ b/arch/sh/boards/mach-se/7724/Makefile @@ -7,4 +7,4 @@ # # -obj-y := setup.o irq.o
\ No newline at end of file +obj-y := setup.o irq.o sdram.o diff --git a/arch/sh/boards/mach-se/7724/sdram.S b/arch/sh/boards/mach-se/7724/sdram.S new file mode 100644 index 000000000000..9040167d5022 --- /dev/null +++ b/arch/sh/boards/mach-se/7724/sdram.S @@ -0,0 +1,52 @@ +/* + * MS7724SE sdram self/auto-refresh setup code + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/sys.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/suspend.h> +#include <asm/romimage-macros.h> + +/* code to enter and leave self-refresh. must be self-contained. + * this code will be copied to on-chip memory and executed from there. + */ + .balign 4 +ENTRY(ms7724se_sdram_enter_start) + + /* DBSC: put memory in self-refresh mode */ + + ED 0xFD000010, 0x00000000 /* DBEN */ + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000040, 0x00000001 /* DBRFPDN0 */ + + rts + nop + +ENTRY(ms7724se_sdram_enter_end) + + .balign 4 +ENTRY(ms7724se_sdram_leave_start) + + /* DBSC: put memory in auto-refresh mode */ + + ED 0xFD000040, 0x00000000 /* DBRFPDN0 */ + WAIT 1 + ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */ + ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */ + ED 0xFD000010, 0x00000001 /* DBEN */ + ED 0xFD000040, 0x00010000 /* DBRFPDN0 */ + + rts + nop + +ENTRY(ms7724se_sdram_leave_end) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 0894bba9fade..4b0f0c0dc2b8 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -19,6 +19,7 @@ #include <linux/smc91x.h> #include <linux/gpio.h> #include <linux/input.h> +#include <linux/input/sh_keysc.h> #include <linux/usb/r8a66597.h> #include <video/sh_mobile_lcdc.h> #include <media/sh_mobile_ceu.h> @@ -27,7 +28,7 @@ #include <asm/heartbeat.h> #include <asm/sh_eth.h> #include <asm/clock.h> -#include <asm/sh_keysc.h> +#include <asm/suspend.h> #include <cpu/sh7724.h> #include <mach-se/mach/se7724.h> @@ -451,6 +452,52 @@ static struct platform_device sh7724_usb1_gadget_device = { .resource = sh7724_usb1_gadget_resources, }; +static struct resource sdhi0_cn7_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi0_cn7_device = { + .name = "sh_mobile_sdhi", + .id = 0, + .num_resources = ARRAY_SIZE(sdhi0_cn7_resources), + .resource = sdhi0_cn7_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + +static struct resource sdhi1_cn8_resources[] = { + [0] = { + .name = "SDHI1", + .start = 0x04cf0000, + .end = 0x04cf01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 24, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi1_cn8_device = { + .name = "sh_mobile_sdhi", + .id = 1, + .num_resources = ARRAY_SIZE(sdhi1_cn8_resources), + .resource = sdhi1_cn8_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI1, + }, +}; + static struct platform_device *ms7724se_devices[] __initdata = { &heartbeat_device, &smc91x_eth_device, @@ -463,6 +510,8 @@ static struct platform_device *ms7724se_devices[] __initdata = { &sh7724_usb0_host_device, &sh7724_usb1_gadget_device, &fsi_device, + &sdhi0_cn7_device, + &sdhi1_cn8_device, }; #define EEPROM_OP 0xBA206000 @@ -487,7 +536,7 @@ static int __init sh_eth_is_eeprom_ready(void) static void __init sh_eth_init(void) { int i; - u16 mac[3]; + u16 mac; /* check EEPROM status */ if (!sh_eth_is_eeprom_ready()) @@ -501,16 +550,10 @@ static void __init sh_eth_init(void) if (!sh_eth_is_eeprom_ready()) return; - mac[i] = ctrl_inw(EEPROM_DATA); - mac[i] = ((mac[i] & 0xFF) << 8) | (mac[i] >> 8); /* swap */ + mac = ctrl_inw(EEPROM_DATA); + sh_eth_plat.mac_addr[i << 1] = mac & 0xff; + sh_eth_plat.mac_addr[(i << 1) + 1] = mac >> 8; } - - /* reset sh-eth */ - ctrl_outl(0x1, SH_ETH_ADDR + 0x0); - - /* set MAC addr */ - ctrl_outl(((mac[0] << 16) | (mac[1])), SH_ETH_MAHR); - ctrl_outl((mac[2]), SH_ETH_MALR); } #define SW4140 0xBA201000 @@ -527,11 +570,22 @@ static void __init sh_eth_init(void) #define SW41_G 0x4000 #define SW41_H 0x8000 +extern char ms7724se_sdram_enter_start; +extern char ms7724se_sdram_enter_end; +extern char ms7724se_sdram_leave_start; +extern char ms7724se_sdram_leave_end; + static int __init devices_setup(void) { u16 sw = ctrl_inw(SW4140); /* select camera, monitor */ struct clk *fsia_clk; + /* register board specific self-refresh code */ + sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF, + &ms7724se_sdram_enter_start, + &ms7724se_sdram_enter_end, + &ms7724se_sdram_leave_start, + &ms7724se_sdram_leave_end); /* Reset Release */ ctrl_outw(ctrl_inw(FPGA_OUT) & ~((1 << 1) | /* LAN */ @@ -701,6 +755,26 @@ static int __init devices_setup(void) clk_set_rate(&fsimcka_clk, 11000); clk_put(fsia_clk); + /* SDHI0 connected to cn7 */ + gpio_request(GPIO_FN_SDHI0CD, NULL); + gpio_request(GPIO_FN_SDHI0WP, NULL); + gpio_request(GPIO_FN_SDHI0D3, NULL); + gpio_request(GPIO_FN_SDHI0D2, NULL); + gpio_request(GPIO_FN_SDHI0D1, NULL); + gpio_request(GPIO_FN_SDHI0D0, NULL); + gpio_request(GPIO_FN_SDHI0CMD, NULL); + gpio_request(GPIO_FN_SDHI0CLK, NULL); + + /* SDHI1 connected to cn8 */ + gpio_request(GPIO_FN_SDHI1CD, NULL); + gpio_request(GPIO_FN_SDHI1WP, NULL); + gpio_request(GPIO_FN_SDHI1D3, NULL); + gpio_request(GPIO_FN_SDHI1D2, NULL); + gpio_request(GPIO_FN_SDHI1D1, NULL); + gpio_request(GPIO_FN_SDHI1D0, NULL); + gpio_request(GPIO_FN_SDHI1CMD, NULL); + gpio_request(GPIO_FN_SDHI1CLK, NULL); + /* * enable SH-Eth * diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c index fd56a71ca9d9..b51b1fc4baae 100644 --- a/arch/sh/boot/compressed/misc.c +++ b/arch/sh/boot/compressed/misc.c @@ -131,7 +131,7 @@ void decompress_kernel(void) #ifdef CONFIG_SUPERH64 output_addr = (CONFIG_MEMORY_START + 0x2000); #else - output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE); + output_addr = __pa((unsigned long)&_text+PAGE_SIZE); #ifdef CONFIG_29BIT output_addr |= P2SEG; #endif diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile index 5806eee84f6f..f473a24a2d92 100644 --- a/arch/sh/boot/romimage/Makefile +++ b/arch/sh/boot/romimage/Makefile @@ -4,16 +4,22 @@ # create an image suitable for burning to flash from zImage # -targets := vmlinux head.o +targets := vmlinux head.o zeropage.bin piggy.o OBJECTS = $(obj)/head.o -LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart +LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart \ + -T $(obj)/../../kernel/vmlinux.lds $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE $(call if_changed,ld) @: +OBJCOPYFLAGS += -j .empty_zero_page + +$(obj)/zeropage.bin: vmlinux FORCE + $(call if_changed,objcopy) + LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T -$(obj)/piggy.o: $(obj)/vmlinux.scr arch/sh/boot/zImage FORCE +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/zeropage.bin arch/sh/boot/zImage FORCE $(call if_changed,ld) diff --git a/arch/sh/boot/romimage/head.S b/arch/sh/boot/romimage/head.S index 219bc626dd71..93e779a405ec 100644 --- a/arch/sh/boot/romimage/head.S +++ b/arch/sh/boot/romimage/head.S @@ -5,6 +5,44 @@ */ .text + #include <asm/page.h> + .global romstart romstart: + /* include board specific setup code */ #include <mach/romimage.h> + + /* copy the empty_zero_page contents to where vmlinux expects it */ + mova empty_zero_page_src, r0 + mov.l empty_zero_page_dst, r1 + mov #(PAGE_SHIFT - 4), r4 + mov #1, r3 + shld r4, r3 /* r3 = PAGE_SIZE / 16 */ + +1: + mov.l @r0, r4 + mov.l @(4, r0), r5 + mov.l @(8, r0), r6 + mov.l @(12, r0), r7 + add #16,r0 + mov.l r4, @r1 + mov.l r5, @(4, r1) + mov.l r6, @(8, r1) + mov.l r7, @(12, r1) + dt r3 + add #16,r1 + bf 1b + + /* jump to the zImage entry point located after the zero page data */ + mov #PAGE_SHIFT, r4 + mov #1, r1 + shld r4, r1 + mova empty_zero_page_src, r0 + add r1, r0 + jmp @r0 + nop + + .align 2 +empty_zero_page_dst: + .long _text +empty_zero_page_src: diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 347ee11351ec..1ee631d3725e 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -13,7 +13,6 @@ #include <linux/init.h> #include <linux/sysdev.h> #include <linux/platform_device.h> -#include <linux/module.h> #include <linux/err.h> #include <linux/string.h> #include <asm/dma.h> @@ -21,7 +20,6 @@ static struct sysdev_class dma_sysclass = { .name = "dma", }; -EXPORT_SYMBOL(dma_sysclass); static ssize_t dma_show_devices(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig deleted file mode 100644 index e8db585a6638..000000000000 --- a/arch/sh/drivers/pci/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -config PCI - bool "PCI support" - depends on SYS_SUPPORTS_PCI - help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. If you have PCI, say Y, otherwise N. - -config SH_PCIDMA_NONCOHERENT - bool "Cache and PCI noncoherent" - depends on PCI - default y - help - Enable this option if your platform does not have a CPU cache which - remains coherent with PCI DMA. It is safest to say 'Y', although you - will see better performance if you can say 'N', because the PCI DMA - code will not have to flush the CPU's caches. If you have a PCI host - bridge integrated with your SH CPU, refer carefully to the chip specs - to see if you can say 'N' here. Otherwise, leave it as 'Y'. diff --git a/arch/sh/include/asm/addrspace.h b/arch/sh/include/asm/addrspace.h index 80d40813e057..99d6b3ecbe22 100644 --- a/arch/sh/include/asm/addrspace.h +++ b/arch/sh/include/asm/addrspace.h @@ -28,9 +28,6 @@ /* Returns the privileged segment base of a given address */ #define PXSEG(a) (((unsigned long)(a)) & 0xe0000000) -/* Returns the physical address of a PnSEG (n=1,2) address */ -#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) - #if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED) /* * Map an address to a certain privileged segment @@ -60,5 +57,11 @@ #define P3_ADDR_MAX P4SEG #endif +#ifndef __ASSEMBLY__ +#ifdef CONFIG_PMB +extern int __in_29bit_mode(void); +#endif /* CONFIG_PMB */ +#endif /* __ASSEMBLY__ */ + #endif /* __KERNEL__ */ #endif /* __ASM_SH_ADDRSPACE_H */ diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h index e8e78137c6f5..b16388d71954 100644 --- a/arch/sh/include/asm/atomic.h +++ b/arch/sh/include/asm/atomic.h @@ -78,11 +78,10 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -/* Atomic operations are already serializing on SH */ -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() #include <asm-generic/atomic-long.h> #include <asm-generic/atomic64.h> diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h index ebe595b7ab1f..98511e4d28cb 100644 --- a/arch/sh/include/asm/bitops.h +++ b/arch/sh/include/asm/bitops.h @@ -26,8 +26,8 @@ /* * clear_bit() doesn't provide any barrier for the compiler. */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() smp_mb() #ifdef CONFIG_SUPERH32 static inline unsigned long ffz(unsigned long word) diff --git a/arch/sh/include/asm/bugs.h b/arch/sh/include/asm/bugs.h index 46260fcbdf4b..02a19a1c033a 100644 --- a/arch/sh/include/asm/bugs.h +++ b/arch/sh/include/asm/bugs.h @@ -14,11 +14,15 @@ #include <asm/processor.h> +extern void select_idle_routine(void); + static void __init check_bugs(void) { extern unsigned long loops_per_jiffy; char *p = &init_utsname()->machine[2]; /* "sh" */ + select_idle_routine(); + current_cpu_data.loops_per_jiffy = loops_per_jiffy; switch (current_cpu_data.family) { diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index 69d56dd4c968..87ced133a363 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -1,219 +1,108 @@ #ifndef __ASM_SH_DMA_MAPPING_H #define __ASM_SH_DMA_MAPPING_H -#include <linux/mm.h> -#include <linux/scatterlist.h> -#include <linux/dma-debug.h> -#include <asm/cacheflush.h> -#include <asm/io.h> +extern struct dma_map_ops *dma_ops; +extern void no_iommu_init(void); + +static inline struct dma_map_ops *get_dma_ops(struct device *dev) +{ + return dma_ops; +} + #include <asm-generic/dma-coherent.h> +#include <asm-generic/dma-mapping-common.h> + +static inline int dma_supported(struct device *dev, u64 mask) +{ + struct dma_map_ops *ops = get_dma_ops(dev); -extern struct bus_type pci_bus_type; + if (ops->dma_supported) + return ops->dma_supported(dev, mask); -#define dma_supported(dev, mask) (1) + return 1; +} static inline int dma_set_mask(struct device *dev, u64 mask) { + struct dma_map_ops *ops = get_dma_ops(dev); + if (!dev->dma_mask || !dma_supported(dev, mask)) return -EIO; + if (ops->set_dma_mask) + return ops->set_dma_mask(dev, mask); *dev->dma_mask = mask; return 0; } -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); - -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); - void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction dir); #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d, h) (1) - -static inline dma_addr_t dma_map_single(struct device *dev, - void *ptr, size_t size, - enum dma_data_direction dir) -{ - dma_addr_t addr = virt_to_phys(ptr); - -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return addr; -#endif - dma_cache_sync(dev, ptr, size, dir); - - debug_dma_map_page(dev, virt_to_page(ptr), - (unsigned long)ptr & ~PAGE_MASK, size, - dir, addr, true); - - return addr; -} - -static inline void dma_unmap_single(struct device *dev, dma_addr_t addr, - size_t size, enum dma_data_direction dir) -{ - debug_dma_unmap_page(dev, addr, size, dir, true); -} -static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; i++) { -#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT) - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); +#ifdef CONFIG_DMA_COHERENT +#define dma_is_consistent(d, h) (1) +#else +#define dma_is_consistent(d, h) (0) #endif - sg[i].dma_address = sg_phys(&sg[i]); - sg[i].dma_length = sg[i].length; - } - debug_dma_map_sg(dev, sg, nents, i, dir); - - return nents; -} - -static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir) -{ - debug_dma_unmap_sg(dev, sg, nents, dir); -} - -static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ - return dma_map_single(dev, page_address(page) + offset, size, dir); -} - -static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, - size_t size, enum dma_data_direction dir) -{ - dma_unmap_single(dev, dma_address, size, dir); -} - -static inline void __dma_sync_single(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction dir) +static inline int dma_get_cache_alignment(void) { -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return; -#endif - dma_cache_sync(dev, phys_to_virt(dma_handle), size, dir); + /* + * Each processor family will define its own L1_CACHE_SHIFT, + * L1_CACHE_BYTES wraps to this, so this is always safe. + */ + return L1_CACHE_BYTES; } -static inline void dma_sync_single_range(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction dir) +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return; -#endif - dma_cache_sync(dev, phys_to_virt(dma_handle) + offset, size, dir); -} + struct dma_map_ops *ops = get_dma_ops(dev); -static inline void __dma_sync_sg(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction dir) -{ - int i; + if (ops->mapping_error) + return ops->mapping_error(dev, dma_addr); - for (i = 0; i < nelems; i++) { -#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT) - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); -#endif - sg[i].dma_address = sg_phys(&sg[i]); - sg[i].dma_length = sg[i].length; - } + return dma_addr == 0; } -static inline void dma_sync_single_for_cpu(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) +static inline void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp) { - __dma_sync_single(dev, dma_handle, size, dir); - debug_dma_sync_single_for_cpu(dev, dma_handle, size, dir); -} + struct dma_map_ops *ops = get_dma_ops(dev); + void *memory; -static inline void dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, - size_t size, - enum dma_data_direction dir) -{ - __dma_sync_single(dev, dma_handle, size, dir); - debug_dma_sync_single_for_device(dev, dma_handle, size, dir); -} + if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) + return memory; + if (!ops->alloc_coherent) + return NULL; -static inline void dma_sync_single_range_for_cpu(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, - size_t size, - enum dma_data_direction direction) -{ - dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); - debug_dma_sync_single_range_for_cpu(dev, dma_handle, - offset, size, direction); -} + memory = ops->alloc_coherent(dev, size, dma_handle, gfp); + debug_dma_alloc_coherent(dev, size, *dma_handle, memory); -static inline void dma_sync_single_range_for_device(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, - size_t size, - enum dma_data_direction direction) -{ - dma_sync_single_for_device(dev, dma_handle+offset, size, direction); - debug_dma_sync_single_range_for_device(dev, dma_handle, - offset, size, direction); + return memory; } - -static inline void dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) +static inline void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) { - __dma_sync_sg(dev, sg, nelems, dir); - debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir); -} + struct dma_map_ops *ops = get_dma_ops(dev); -static inline void dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - __dma_sync_sg(dev, sg, nelems, dir); - debug_dma_sync_sg_for_device(dev, sg, nelems, dir); -} + WARN_ON(irqs_disabled()); /* for portability */ -static inline int dma_get_cache_alignment(void) -{ - /* - * Each processor family will define its own L1_CACHE_SHIFT, - * L1_CACHE_BYTES wraps to this, so this is always safe. - */ - return L1_CACHE_BYTES; -} + if (dma_release_from_coherent(dev, get_order(size), vaddr)) + return; -static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return dma_addr == 0; + debug_dma_free_coherent(dev, size, vaddr, dma_handle); + if (ops->free_coherent) + ops->free_coherent(dev, size, vaddr, dma_handle); } -#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY - -extern int -dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, - dma_addr_t device_addr, size_t size, int flags); - -extern void -dma_release_declared_memory(struct device *dev); - -extern void * -dma_mark_declared_memory_occupied(struct device *dev, - dma_addr_t device_addr, size_t size); +/* arch/sh/mm/consistent.c */ +extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_addr, gfp_t flag); +extern void dma_generic_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); #endif /* __ASM_SH_DMA_MAPPING_H */ diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h index ced6795891a6..bdccbbfdc0bd 100644 --- a/arch/sh/include/asm/dwarf.h +++ b/arch/sh/include/asm/dwarf.h @@ -194,6 +194,12 @@ #define DWARF_ARCH_RA_REG 17 #ifndef __ASSEMBLY__ + +#include <linux/compiler.h> +#include <linux/bug.h> +#include <linux/list.h> +#include <linux/module.h> + /* * Read either the frame pointer (r14) or the stack pointer (r15). * NOTE: this MUST be inlined. @@ -241,6 +247,12 @@ struct dwarf_cie { unsigned long flags; #define DWARF_CIE_Z_AUGMENTATION (1 << 0) + + /* + * 'mod' will be non-NULL if this CIE came from a module's + * .eh_frame section. + */ + struct module *mod; }; /** @@ -255,6 +267,12 @@ struct dwarf_fde { unsigned char *instructions; unsigned char *end; struct list_head link; + + /* + * 'mod' will be non-NULL if this FDE came from a module's + * .eh_frame section. + */ + struct module *mod; }; /** @@ -364,6 +382,12 @@ static inline unsigned int DW_CFA_operand(unsigned long insn) extern struct dwarf_frame *dwarf_unwind_stack(unsigned long, struct dwarf_frame *); +extern void dwarf_free_frame(struct dwarf_frame *); + +extern int module_dwarf_finalize(const Elf_Ehdr *, const Elf_Shdr *, + struct module *); +extern void module_dwarf_cleanup(struct module *); + #endif /* !__ASSEMBLY__ */ #define CFI_STARTPROC .cfi_startproc @@ -391,6 +415,10 @@ extern struct dwarf_frame *dwarf_unwind_stack(unsigned long, static inline void dwarf_unwinder_init(void) { } + +#define module_dwarf_finalize(hdr, sechdrs, me) (0) +#define module_dwarf_cleanup(mod) do { } while (0) + #endif #endif /* CONFIG_DWARF_UNWINDER */ diff --git a/arch/sh/include/asm/fixmap.h b/arch/sh/include/asm/fixmap.h index 721fcc4d5e98..5ac1e40a511c 100644 --- a/arch/sh/include/asm/fixmap.h +++ b/arch/sh/include/asm/fixmap.h @@ -14,9 +14,9 @@ #define _ASM_FIXMAP_H #include <linux/kernel.h> +#include <linux/threads.h> #include <asm/page.h> #ifdef CONFIG_HIGHMEM -#include <linux/threads.h> #include <asm/kmap_types.h> #endif @@ -46,9 +46,15 @@ * fix-mapped? */ enum fixed_addresses { -#define FIX_N_COLOURS 16 + /* + * The FIX_CMAP entries are used by kmap_coherent() to get virtual + * addresses which are of a known color, and so their values are + * important. __fix_to_virt(FIX_CMAP_END - n) must give an address + * which is the same color as a page (n<<PAGE_SHIFT). + */ +#define FIX_N_COLOURS 8 FIX_CMAP_BEGIN, - FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, + FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS) - 1, FIX_UNCACHED, #ifdef CONFIG_HIGHMEM FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ diff --git a/arch/sh/include/asm/fpu.h b/arch/sh/include/asm/fpu.h index 1d3aee04b5cc..fb6bbb9b1cc8 100644 --- a/arch/sh/include/asm/fpu.h +++ b/arch/sh/include/asm/fpu.h @@ -18,16 +18,15 @@ static inline void grab_fpu(struct pt_regs *regs) struct task_struct; -extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); +extern void save_fpu(struct task_struct *__tsk); +void fpu_state_restore(struct pt_regs *regs); #else +#define save_fpu(tsk) do { } while (0) #define release_fpu(regs) do { } while (0) #define grab_fpu(regs) do { } while (0) +#define fpu_state_restore(regs) do { } while (0) -static inline void save_fpu(struct task_struct *tsk, struct pt_regs *regs) -{ - clear_tsk_thread_flag(tsk, TIF_USEDFPU); -} #endif struct user_regset; @@ -39,19 +38,28 @@ extern int fpregs_get(struct task_struct *target, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +static inline void __unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs) +{ + if (task_thread_info(tsk)->status & TS_USEDFPU) { + task_thread_info(tsk)->status &= ~TS_USEDFPU; + save_fpu(tsk); + release_fpu(regs); + } else + tsk->fpu_counter = 0; +} + static inline void unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs) { preempt_disable(); - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) - save_fpu(tsk, regs); + __unlazy_fpu(tsk, regs); preempt_enable(); } static inline void clear_fpu(struct task_struct *tsk, struct pt_regs *regs) { preempt_disable(); - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { - clear_tsk_thread_flag(tsk, TIF_USEDFPU); + if (task_thread_info(tsk)->status & TS_USEDFPU) { + task_thread_info(tsk)->status &= ~TS_USEDFPU; release_fpu(regs); } preempt_enable(); diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h index 12f3a31f20af..13e9966464c2 100644 --- a/arch/sh/include/asm/ftrace.h +++ b/arch/sh/include/asm/ftrace.h @@ -35,4 +35,21 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ +#ifndef __ASSEMBLY__ + +/* arch/sh/kernel/return_address.c */ +extern void *return_address(unsigned int); + +#define HAVE_ARCH_CALLER_ADDR + +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) +#define CALLER_ADDR1 ((unsigned long)return_address(1)) +#define CALLER_ADDR2 ((unsigned long)return_address(2)) +#define CALLER_ADDR3 ((unsigned long)return_address(3)) +#define CALLER_ADDR4 ((unsigned long)return_address(4)) +#define CALLER_ADDR5 ((unsigned long)return_address(5)) +#define CALLER_ADDR6 ((unsigned long)return_address(6)) + +#endif /* __ASSEMBLY__ */ + #endif /* __ASM_SH_FTRACE_H */ diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 61f93da2c62e..f8d9a731e903 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -20,7 +20,7 @@ #endif #define ARCH_NR_GPIOS 512 -#include <asm-generic/gpio.h> +#include <linux/sh_pfc.h> #ifdef CONFIG_GPIOLIB @@ -53,84 +53,4 @@ static inline int irq_to_gpio(unsigned int irq) #endif /* CONFIG_GPIOLIB */ -typedef unsigned short pinmux_enum_t; -typedef unsigned short pinmux_flag_t; - -#define PINMUX_TYPE_NONE 0 -#define PINMUX_TYPE_FUNCTION 1 -#define PINMUX_TYPE_GPIO 2 -#define PINMUX_TYPE_OUTPUT 3 -#define PINMUX_TYPE_INPUT 4 -#define PINMUX_TYPE_INPUT_PULLUP 5 -#define PINMUX_TYPE_INPUT_PULLDOWN 6 - -#define PINMUX_FLAG_TYPE (0x7) -#define PINMUX_FLAG_WANT_PULLUP (1 << 3) -#define PINMUX_FLAG_WANT_PULLDOWN (1 << 4) - -#define PINMUX_FLAG_DBIT_SHIFT 5 -#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT) -#define PINMUX_FLAG_DREG_SHIFT 10 -#define PINMUX_FLAG_DREG (0x3f << PINMUX_FLAG_DREG_SHIFT) - -struct pinmux_gpio { - pinmux_enum_t enum_id; - pinmux_flag_t flags; -}; - -#define PINMUX_GPIO(gpio, data_or_mark) [gpio] = { data_or_mark } -#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0 - -struct pinmux_cfg_reg { - unsigned long reg, reg_width, field_width; - unsigned long *cnt; - pinmux_enum_t *enum_ids; -}; - -#define PINMUX_CFG_REG(name, r, r_width, f_width) \ - .reg = r, .reg_width = r_width, .field_width = f_width, \ - .cnt = (unsigned long [r_width / f_width]) {}, \ - .enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \ - -struct pinmux_data_reg { - unsigned long reg, reg_width, reg_shadow; - pinmux_enum_t *enum_ids; -}; - -#define PINMUX_DATA_REG(name, r, r_width) \ - .reg = r, .reg_width = r_width, \ - .enum_ids = (pinmux_enum_t [r_width]) \ - -struct pinmux_range { - pinmux_enum_t begin; - pinmux_enum_t end; - pinmux_enum_t force; -}; - -struct pinmux_info { - char *name; - pinmux_enum_t reserved_id; - struct pinmux_range data; - struct pinmux_range input; - struct pinmux_range input_pd; - struct pinmux_range input_pu; - struct pinmux_range output; - struct pinmux_range mark; - struct pinmux_range function; - - unsigned first_gpio, last_gpio; - - struct pinmux_gpio *gpios; - struct pinmux_cfg_reg *cfg_regs; - struct pinmux_data_reg *data_regs; - - pinmux_enum_t *gpio_data; - unsigned int gpio_data_size; - - unsigned long *gpio_in_use; - struct gpio_chip chip; -}; - -int register_pinmux(struct pinmux_info *pip); - #endif /* __ASM_SH_GPIO_H */ diff --git a/arch/sh/include/asm/hardirq.h b/arch/sh/include/asm/hardirq.h index a5be4afa790b..48b191313a99 100644 --- a/arch/sh/include/asm/hardirq.h +++ b/arch/sh/include/asm/hardirq.h @@ -1,9 +1,16 @@ #ifndef __ASM_SH_HARDIRQ_H #define __ASM_SH_HARDIRQ_H -extern void ack_bad_irq(unsigned int irq); -#define ack_bad_irq ack_bad_irq +#include <linux/threads.h> +#include <linux/irq.h> + +typedef struct { + unsigned int __softirq_pending; + unsigned int __nmi_count; /* arch dependent */ +} ____cacheline_aligned irq_cpustat_t; -#include <asm-generic/hardirq.h> +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ + +extern void ack_bad_irq(unsigned int irq); #endif /* __ASM_SH_HARDIRQ_H */ diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 5be45ea4dfec..512cd3e9d0ca 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -90,15 +90,11 @@ #define ctrl_outl __raw_writel #define ctrl_outq __raw_writeq +extern unsigned long generic_io_base; + static inline void ctrl_delay(void) { -#ifdef CONFIG_CPU_SH4 - __raw_readw(CCN_PVR); -#elif defined(P2SEG) - __raw_readw(P2SEG); -#else -#error "Need a dummy address for delay" -#endif + __raw_readw(generic_io_base); } #define __BUILD_MEMORY_STRING(bwlq, type) \ @@ -186,8 +182,6 @@ __BUILD_MEMORY_STRING(q, u64) #define IO_SPACE_LIMIT 0xffffffff -extern unsigned long generic_io_base; - /* * This function provides a method for the generic case where a * board-specific ioport_map simply needs to return the port + some @@ -246,7 +240,7 @@ void __iounmap(void __iomem *addr); static inline void __iomem * __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { -#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB) unsigned long last_addr = offset + size - 1; #endif void __iomem *ret; @@ -255,7 +249,7 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) if (ret) return ret; -#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB) /* * For P1 and P2 space this is trivial, as everything is already * mapped. Uncached access for P1 addresses are done through P2. diff --git a/arch/sh/include/asm/irqflags.h b/arch/sh/include/asm/irqflags.h index 46e71da5be6b..a741153b41c2 100644 --- a/arch/sh/include/asm/irqflags.h +++ b/arch/sh/include/asm/irqflags.h @@ -1,34 +1,9 @@ #ifndef __ASM_SH_IRQFLAGS_H #define __ASM_SH_IRQFLAGS_H -#ifdef CONFIG_SUPERH32 -#include "irqflags_32.h" -#else -#include "irqflags_64.h" -#endif +#define RAW_IRQ_DISABLED 0xf0 +#define RAW_IRQ_ENABLED 0x00 -#define raw_local_save_flags(flags) \ - do { (flags) = __raw_local_save_flags(); } while (0) - -static inline int raw_irqs_disabled_flags(unsigned long flags) -{ - return (flags != 0); -} - -static inline int raw_irqs_disabled(void) -{ - unsigned long flags = __raw_local_save_flags(); - - return raw_irqs_disabled_flags(flags); -} - -#define raw_local_irq_save(flags) \ - do { (flags) = __raw_local_irq_save(); } while (0) - -static inline void raw_local_irq_restore(unsigned long flags) -{ - if ((flags & 0xf0) != 0xf0) - raw_local_irq_enable(); -} +#include <asm-generic/irqflags.h> #endif /* __ASM_SH_IRQFLAGS_H */ diff --git a/arch/sh/include/asm/irqflags_32.h b/arch/sh/include/asm/irqflags_32.h deleted file mode 100644 index 60218f541340..000000000000 --- a/arch/sh/include/asm/irqflags_32.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef __ASM_SH_IRQFLAGS_32_H -#define __ASM_SH_IRQFLAGS_32_H - -static inline void raw_local_irq_enable(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and %1, %0\n\t" -#ifdef CONFIG_CPU_HAS_SR_RB - "stc r6_bank, %1\n\t" - "or %1, %0\n\t" -#endif - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x000000f0) - : "memory" - ); -} - -static inline void raw_local_irq_disable(void) -{ - unsigned long flags; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "or #0xf0, %0\n\t" - "ldc %0, sr\n\t" - : "=&z" (flags) - : /* no inputs */ - : "memory" - ); -} - -static inline void set_bl_bit(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "or %2, %0\n\t" - "and %3, %0\n\t" - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "r" (0x10000000), "r" (0xffffff0f) - : "memory" - ); -} - -static inline void clear_bl_bit(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and %2, %0\n\t" - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x10000000) - : "memory" - ); -} - -static inline unsigned long __raw_local_save_flags(void) -{ - unsigned long flags; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and #0xf0, %0\n\t" - : "=&z" (flags) - : /* no inputs */ - : "memory" - ); - - return flags; -} - -static inline unsigned long __raw_local_irq_save(void) -{ - unsigned long flags, __dummy; - - __asm__ __volatile__ ( - "stc sr, %1\n\t" - "mov %1, %0\n\t" - "or #0xf0, %0\n\t" - "ldc %0, sr\n\t" - "mov %1, %0\n\t" - "and #0xf0, %0\n\t" - : "=&z" (flags), "=&r" (__dummy) - : /* no inputs */ - : "memory" - ); - - return flags; -} - -#endif /* __ASM_SH_IRQFLAGS_32_H */ diff --git a/arch/sh/include/asm/irqflags_64.h b/arch/sh/include/asm/irqflags_64.h deleted file mode 100644 index 88f65222c1d4..000000000000 --- a/arch/sh/include/asm/irqflags_64.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __ASM_SH_IRQFLAGS_64_H -#define __ASM_SH_IRQFLAGS_64_H - -#include <cpu/registers.h> - -#define SR_MASK_LL 0x00000000000000f0LL -#define SR_BL_LL 0x0000000010000000LL - -static inline void raw_local_irq_enable(void) -{ - unsigned long long __dummy0, __dummy1 = ~SR_MASK_LL; - - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "and %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} - -static inline void raw_local_irq_disable(void) -{ - unsigned long long __dummy0, __dummy1 = SR_MASK_LL; - - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "or %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} - -static inline void set_bl_bit(void) -{ - unsigned long long __dummy0, __dummy1 = SR_BL_LL; - - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "or %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); - -} - -static inline void clear_bl_bit(void) -{ - unsigned long long __dummy0, __dummy1 = ~SR_BL_LL; - - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "and %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} - -static inline unsigned long __raw_local_save_flags(void) -{ - unsigned long long __dummy = SR_MASK_LL; - unsigned long flags; - - __asm__ __volatile__ ( - "getcon " __SR ", %0\n\t" - "and %0, %1, %0" - : "=&r" (flags) - : "r" (__dummy)); - - return flags; -} - -static inline unsigned long __raw_local_irq_save(void) -{ - unsigned long long __dummy0, __dummy1 = SR_MASK_LL; - unsigned long flags; - - __asm__ __volatile__ ( - "getcon " __SR ", %1\n\t" - "or %1, r63, %0\n\t" - "or %1, %2, %1\n\t" - "putcon %1, " __SR "\n\t" - "and %0, %2, %0" - : "=&r" (flags), "=&r" (__dummy0) - : "r" (__dummy1)); - - return flags; -} - -#endif /* __ASM_SH_IRQFLAGS_64_H */ diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h index f5963037c9d6..c7426ad9926e 100644 --- a/arch/sh/include/asm/mmu.h +++ b/arch/sh/include/asm/mmu.h @@ -7,12 +7,16 @@ #define PMB_PASCR 0xff000070 #define PMB_IRMCR 0xff000078 +#define PASCR_SE 0x80000000 + #define PMB_ADDR 0xf6100000 #define PMB_DATA 0xf7100000 #define PMB_ENTRY_MAX 16 #define PMB_E_MASK 0x0000000f #define PMB_E_SHIFT 8 +#define PMB_PFN_MASK 0xff000000 + #define PMB_SZ_16M 0x00000000 #define PMB_SZ_64M 0x00000010 #define PMB_SZ_128M 0x00000080 @@ -62,17 +66,10 @@ struct pmb_entry { }; /* arch/sh/mm/pmb.c */ -int __set_pmb_entry(unsigned long vpn, unsigned long ppn, - unsigned long flags, int *entry); -int set_pmb_entry(struct pmb_entry *pmbe); -void clear_pmb_entry(struct pmb_entry *pmbe); -struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, - unsigned long flags); -void pmb_free(struct pmb_entry *pmbe); long pmb_remap(unsigned long virt, unsigned long phys, unsigned long size, unsigned long flags); void pmb_unmap(unsigned long addr); +int pmb_init(void); #endif /* __ASSEMBLY__ */ #endif /* __MMU_H */ - diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 4163950cd1c6..67f3999b544e 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h @@ -3,8 +3,6 @@ #ifdef __KERNEL__ -#include <linux/dma-mapping.h> - /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ @@ -54,30 +52,18 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) * address space. The networking and block device layers use * this boolean for bounce buffer decisions. */ -#define PCI_DMA_BUS_IS_PHYS (1) - -#include <linux/types.h> -#include <linux/slab.h> -#include <asm/scatterlist.h> -#include <linux/string.h> -#include <asm/io.h> +#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) /* pci_unmap_{single,page} being a nop depends upon the * configuration. */ -#ifdef CONFIG_SH_PCIDMA_NONCOHERENT -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ - dma_addr_t ADDR_NAME; -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ - __u32 LEN_NAME; -#define pci_unmap_addr(PTR, ADDR_NAME) \ - ((PTR)->ADDR_NAME) -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ - (((PTR)->ADDR_NAME) = (VAL)) -#define pci_unmap_len(PTR, LEN_NAME) \ - ((PTR)->LEN_NAME) -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ - (((PTR)->LEN_NAME) = (VAL)) +#ifdef CONFIG_DMA_NONCOHERENT +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME; +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME; +#define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) +#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) #else #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) diff --git a/arch/sh/include/asm/perf_event.h b/arch/sh/include/asm/perf_event.h index 11a302297ab7..3d0c9f36d150 100644 --- a/arch/sh/include/asm/perf_event.h +++ b/arch/sh/include/asm/perf_event.h @@ -1,8 +1,35 @@ #ifndef __ASM_SH_PERF_EVENT_H #define __ASM_SH_PERF_EVENT_H -/* SH only supports software events through this interface. */ -static inline void set_perf_event_pending(void) {} +struct hw_perf_event; + +#define MAX_HWEVENTS 2 + +struct sh_pmu { + const char *name; + unsigned int num_events; + void (*disable_all)(void); + void (*enable_all)(void); + void (*enable)(struct hw_perf_event *, int); + void (*disable)(struct hw_perf_event *, int); + u64 (*read)(int); + int (*event_map)(int); + unsigned int max_events; + unsigned long raw_event_mask; + const int (*cache_events)[PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX]; +}; + +/* arch/sh/kernel/perf_event.c */ +extern int register_sh_pmu(struct sh_pmu *); +extern int reserve_pmc_hardware(void); +extern void release_pmc_hardware(void); + +static inline void set_perf_event_pending(void) +{ + /* Nothing to see here, move along. */ +} #define PERF_EVENT_INDEX_OFFSET 0 diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index 4f3efa7d5a64..ba3046e4f06f 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -75,13 +75,31 @@ static inline unsigned long long neff_sign_extend(unsigned long val) #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_ADDRESS 0 -#ifdef CONFIG_32BIT -#define PHYS_ADDR_MASK 0xffffffff +#define PHYS_ADDR_MASK29 0x1fffffff +#define PHYS_ADDR_MASK32 0xffffffff + +#ifdef CONFIG_PMB +static inline unsigned long phys_addr_mask(void) +{ + /* Is the MMU in 29bit mode? */ + if (__in_29bit_mode()) + return PHYS_ADDR_MASK29; + + return PHYS_ADDR_MASK32; +} +#elif defined(CONFIG_32BIT) +static inline unsigned long phys_addr_mask(void) +{ + return PHYS_ADDR_MASK32; +} #else -#define PHYS_ADDR_MASK 0x1fffffff +static inline unsigned long phys_addr_mask(void) +{ + return PHYS_ADDR_MASK29; +} #endif -#define PTE_PHYS_MASK (PHYS_ADDR_MASK & PAGE_MASK) +#define PTE_PHYS_MASK (phys_addr_mask() & PAGE_MASK) #define PTE_FLAGS_MASK (~(PTE_PHYS_MASK) << PAGE_SHIFT) #ifdef CONFIG_SUPERH32 diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index c0d359ce337b..b35435516203 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h @@ -108,7 +108,7 @@ static inline unsigned long copy_ptea_attributes(unsigned long x) #define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE) #endif -#define _PAGE_FLAGS_HARDWARE_MASK (PHYS_ADDR_MASK & ~(_PAGE_CLEAR_FLAGS)) +#define _PAGE_FLAGS_HARDWARE_MASK (phys_addr_mask() & ~(_PAGE_CLEAR_FLAGS)) /* Hardware flags, page size encoding */ #if !defined(CONFIG_MMU) diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index 9a8714945dc9..1f3d6fab660c 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -56,6 +56,7 @@ asmlinkage void __init sh_cpu_init(void); #define SR_DSP 0x00001000 #define SR_IMASK 0x000000f0 #define SR_FD 0x00008000 +#define SR_MD 0x40000000 /* * DSP structure and data @@ -136,7 +137,7 @@ struct mm_struct; extern void release_thread(struct task_struct *); /* Prepare to copy thread state - unlazy all lazy status */ -#define prepare_to_copy(tsk) do { } while (0) +void prepare_to_copy(struct task_struct *tsk); /* * create a kernel thread without removing it from tasklists diff --git a/arch/sh/include/asm/scatterlist.h b/arch/sh/include/asm/scatterlist.h index 327cc2e4c97b..e38d1d4c7f6f 100644 --- a/arch/sh/include/asm/scatterlist.h +++ b/arch/sh/include/asm/scatterlist.h @@ -1,7 +1,7 @@ #ifndef __ASM_SH_SCATTERLIST_H #define __ASM_SH_SCATTERLIST_H -#define ISA_DMA_THRESHOLD PHYS_ADDR_MASK +#define ISA_DMA_THRESHOLD phys_addr_mask() #include <asm-generic/scatterlist.h> diff --git a/arch/sh/include/asm/sh_keysc.h b/arch/sh/include/asm/sh_keysc.h deleted file mode 100644 index 4a65b1e40eab..000000000000 --- a/arch/sh/include/asm/sh_keysc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __ASM_KEYSC_H__ -#define __ASM_KEYSC_H__ - -#define SH_KEYSC_MAXKEYS 30 - -struct sh_keysc_info { - enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3 } mode; - int scan_timing; /* 0 -> 7, see KYCR1, SCN[2:0] */ - int delay; - int kycr2_delay; - int keycodes[SH_KEYSC_MAXKEYS]; -}; - -#endif /* __ASM_KEYSC_H__ */ diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h index 5c8ea28ff7a4..fe9c2a1ad047 100644 --- a/arch/sh/include/asm/suspend.h +++ b/arch/sh/include/asm/suspend.h @@ -2,6 +2,7 @@ #define _ASM_SH_SUSPEND_H #ifndef __ASSEMBLY__ +#include <linux/notifier.h> static inline int arch_prepare_suspend(void) { return 0; } #include <asm/ptrace.h> @@ -19,6 +20,69 @@ void sh_mobile_setup_cpuidle(void); static inline void sh_mobile_setup_cpuidle(void) {} #endif +/* notifier chains for pre/post sleep hooks */ +extern struct atomic_notifier_head sh_mobile_pre_sleep_notifier_list; +extern struct atomic_notifier_head sh_mobile_post_sleep_notifier_list; + +/* priority levels for notifiers */ +#define SH_MOBILE_SLEEP_BOARD 0 +#define SH_MOBILE_SLEEP_CPU 1 +#define SH_MOBILE_PRE(x) (x) +#define SH_MOBILE_POST(x) (-(x)) + +/* board code registration function for self-refresh assembly snippets */ +void sh_mobile_register_self_refresh(unsigned long flags, + void *pre_start, void *pre_end, + void *post_start, void *post_end); + +/* register structure for address/data information */ +struct sh_sleep_regs { + unsigned long stbcr; + unsigned long bar; + + /* MMU */ + unsigned long pteh; + unsigned long ptel; + unsigned long ttb; + unsigned long tea; + unsigned long mmucr; + unsigned long ptea; + unsigned long pascr; + unsigned long irmcr; + + /* Cache */ + unsigned long ccr; + unsigned long ramcr; +}; + +/* data area for low-level sleep code */ +struct sh_sleep_data { + /* current sleep mode (SUSP_SH_...) */ + unsigned long mode; + + /* addresses of board specific self-refresh snippets */ + unsigned long sf_pre; + unsigned long sf_post; + + /* address of resume code */ + unsigned long resume; + + /* register state saved and restored by the assembly code */ + unsigned long vbr; + unsigned long spc; + unsigned long sr; + unsigned long sp; + + /* structure for keeping register addresses */ + struct sh_sleep_regs addr; + + /* structure for saving/restoring register state */ + struct sh_sleep_regs data; +}; + +/* a bitmap of supported sleep modes (SUSP_SH..) */ +extern unsigned long sh_mobile_sleep_supported; + #endif /* flags passed to assembly suspend code */ @@ -27,5 +91,6 @@ static inline void sh_mobile_setup_cpuidle(void) {} #define SUSP_SH_RSTANDBY (1 << 2) /* SH-Mobile R-standby mode */ #define SUSP_SH_USTANDBY (1 << 3) /* SH-Mobile U-standby mode */ #define SUSP_SH_SF (1 << 4) /* Enable self-refresh */ +#define SUSP_SH_MMU (1 << 5) /* Save/restore MMU and cache */ #endif /* _ASM_SH_SUSPEND_H */ diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h index b5c5acdc8c0e..c15415b4b169 100644 --- a/arch/sh/include/asm/system.h +++ b/arch/sh/include/asm/system.h @@ -171,10 +171,6 @@ BUILD_TRAP_HANDLER(fpu_error); BUILD_TRAP_HANDLER(fpu_state_restore); BUILD_TRAP_HANDLER(nmi); -#ifdef CONFIG_BUG -extern void handle_BUG(struct pt_regs *); -#endif - #define arch_align_stack(x) (x) struct mem_access { diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h index 607d413f6168..06814f5b59c7 100644 --- a/arch/sh/include/asm/system_32.h +++ b/arch/sh/include/asm/system_32.h @@ -232,4 +232,33 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs __regs); +static inline void set_bl_bit(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "or %2, %0\n\t" + "and %3, %0\n\t" + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "r" (0x10000000), "r" (0xffffff0f) + : "memory" + ); +} + +static inline void clear_bl_bit(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and %2, %0\n\t" + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "1" (~0x10000000) + : "memory" + ); +} + #endif /* __ASM_SH_SYSTEM_32_H */ diff --git a/arch/sh/include/asm/system_64.h b/arch/sh/include/asm/system_64.h index 8e4a03e7966c..ab1dd917ea87 100644 --- a/arch/sh/include/asm/system_64.h +++ b/arch/sh/include/asm/system_64.h @@ -12,6 +12,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#include <cpu/registers.h> #include <asm/processor.h> /* @@ -47,4 +48,29 @@ static inline reg_size_t register_align(void *val) return (unsigned long long)(signed long long)(signed long)val; } +#define SR_BL_LL 0x0000000010000000LL + +static inline void set_bl_bit(void) +{ + unsigned long long __dummy0, __dummy1 = SR_BL_LL; + + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "or %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); + +} + +static inline void clear_bl_bit(void) +{ + unsigned long long __dummy0, __dummy1 = ~SR_BL_LL; + + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "and %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); +} + #endif /* __ASM_SH_SYSTEM_64_H */ diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index bdeb9d46d17d..1f3d927e2265 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h @@ -19,6 +19,7 @@ struct thread_info { struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ unsigned long flags; /* low level flags */ + __u32 status; /* thread synchronous flags */ __u32 cpu; int preempt_count; /* 0 => preemptable, <0 => BUG */ mm_segment_t addr_limit; /* thread address space */ @@ -50,6 +51,7 @@ struct thread_info { .task = &tsk, \ .exec_domain = &default_exec_domain, \ .flags = 0, \ + .status = 0, \ .cpu = 0, \ .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ @@ -111,13 +113,11 @@ extern void free_thread_info(struct thread_info *ti); #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ #define TIF_SIGPENDING 1 /* signal pending */ #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ -#define TIF_RESTORE_SIGMASK 3 /* restore signal mask in do_signal() */ #define TIF_SINGLESTEP 4 /* singlestepping active */ #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ #define TIF_SECCOMP 6 /* secure computing */ #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ #define TIF_SYSCALL_TRACEPOINT 8 /* for ftrace syscall instrumentation */ -#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 18 #define TIF_FREEZE 19 /* Freezing for suspend */ @@ -125,13 +125,11 @@ extern void free_thread_info(struct thread_info *ti); #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) -#define _TIF_USEDFPU (1 << TIF_USEDFPU) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_FREEZE (1 << TIF_FREEZE) @@ -149,13 +147,33 @@ extern void free_thread_info(struct thread_info *ti); /* work to do on any return to u-space */ #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ - _TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \ - _TIF_NOTIFY_RESUME | _TIF_SYSCALL_TRACEPOINT) + _TIF_SINGLESTEP | _TIF_NOTIFY_RESUME | \ + _TIF_SYSCALL_TRACEPOINT) /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)) +/* + * Thread-synchronous status. + * + * This is different from the flags in that nobody else + * ever touches our thread-synchronous status, so we don't + * have to worry about atomic accesses. + */ +#define TS_RESTORE_SIGMASK 0x0001 /* restore signal mask in do_signal() */ +#define TS_USEDFPU 0x0002 /* FPU used by this task this quantum */ + +#ifndef __ASSEMBLY__ +#define HAVE_SET_RESTORE_SIGMASK 1 +static inline void set_restore_sigmask(void) +{ + struct thread_info *ti = current_thread_info(); + ti->status |= TS_RESTORE_SIGMASK; + set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); +} +#endif /* !__ASSEMBLY__ */ + #endif /* __KERNEL__ */ #endif /* __ASM_SH_THREAD_INFO_H */ diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h index 65e7bd2f2240..37cdadd975ac 100644 --- a/arch/sh/include/asm/topology.h +++ b/arch/sh/include/asm/topology.h @@ -40,6 +40,14 @@ #endif +#define mc_capable() (1) + +const struct cpumask *cpu_coregroup_mask(unsigned int cpu); + +extern cpumask_t cpu_core_map[NR_CPUS]; + +#define topology_core_cpumask(cpu) (&cpu_core_map[cpu]) + #include <asm-generic/topology.h> #endif /* _ASM_SH_TOPOLOGY_H */ diff --git a/arch/sh/include/asm/ubc.h b/arch/sh/include/asm/ubc.h index 4ca4b7717371..9bf961684431 100644 --- a/arch/sh/include/asm/ubc.h +++ b/arch/sh/include/asm/ubc.h @@ -60,16 +60,5 @@ #define BRCR_UBDE (1 << 0) #endif -#ifndef __ASSEMBLY__ -/* arch/sh/kernel/cpu/ubc.S */ -extern void ubc_sleep(void); - -#ifdef CONFIG_UBC_WAKEUP -extern void ubc_wakeup(void); -#else -#define ubc_wakeup() do { } while (0) -#endif -#endif - #endif /* __KERNEL__ */ #endif /* __ASM_SH_UBC_H */ diff --git a/arch/sh/include/asm/watchdog.h b/arch/sh/include/asm/watchdog.h index 2fe7cee9e43a..19dfff5c8511 100644 --- a/arch/sh/include/asm/watchdog.h +++ b/arch/sh/include/asm/watchdog.h @@ -2,6 +2,8 @@ * include/asm-sh/watchdog.h * * Copyright (C) 2002, 2003 Paul Mundt + * Copyright (C) 2009 Siemens AG + * Copyright (C) 2009 Valentin Sitdikov * * 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 @@ -61,6 +63,61 @@ #define WTCSR_CKS_2048 0x06 #define WTCSR_CKS_4096 0x07 +#if defined(CONFIG_CPU_SUBTYPE_SH7785) || defined(CONFIG_CPU_SUBTYPE_SH7780) +/** + * sh_wdt_read_cnt - Read from Counter + * Reads back the WTCNT value. + */ +static inline __u32 sh_wdt_read_cnt(void) +{ + return ctrl_inl(WTCNT_R); +} + +/** + * sh_wdt_write_cnt - Write to Counter + * @val: Value to write + * + * Writes the given value @val to the lower byte of the timer counter. + * The upper byte is set manually on each write. + */ +static inline void sh_wdt_write_cnt(__u32 val) +{ + ctrl_outl((WTCNT_HIGH << 24) | (__u32)val, WTCNT); +} + +/** + * sh_wdt_write_bst - Write to Counter + * @val: Value to write + * + * Writes the given value @val to the lower byte of the timer counter. + * The upper byte is set manually on each write. + */ +static inline void sh_wdt_write_bst(__u32 val) +{ + ctrl_outl((WTBST_HIGH << 24) | (__u32)val, WTBST); +} +/** + * sh_wdt_read_csr - Read from Control/Status Register + * + * Reads back the WTCSR value. + */ +static inline __u32 sh_wdt_read_csr(void) +{ + return ctrl_inl(WTCSR_R); +} + +/** + * sh_wdt_write_csr - Write to Control/Status Register + * @val: Value to write + * + * Writes the given value @val to the lower byte of the control/status + * register. The upper byte is set manually on each write. + */ +static inline void sh_wdt_write_csr(__u32 val) +{ + ctrl_outl((WTCSR_HIGH << 24) | (__u32)val, WTCSR); +} +#else /** * sh_wdt_read_cnt - Read from Counter * Reads back the WTCNT value. @@ -103,6 +160,6 @@ static inline void sh_wdt_write_csr(__u8 val) { ctrl_outw((WTCSR_HIGH << 8) | (__u16)val, WTCSR); } - +#endif /* CONFIG_CPU_SUBTYPE_SH7785 || CONFIG_CPU_SUBTYPE_SH7780 */ #endif /* __KERNEL__ */ #endif /* __ASM_SH_WATCHDOG_H */ diff --git a/arch/sh/include/cpu-sh4/cpu/watchdog.h b/arch/sh/include/cpu-sh4/cpu/watchdog.h index 259f6a0ce23d..7672301d0c70 100644 --- a/arch/sh/include/cpu-sh4/cpu/watchdog.h +++ b/arch/sh/include/cpu-sh4/cpu/watchdog.h @@ -2,6 +2,8 @@ * include/asm-sh/cpu-sh4/watchdog.h * * Copyright (C) 2002, 2003 Paul Mundt + * Copyright (C) 2009 Siemens AG + * Copyright (C) 2009 Sitdikov Valentin * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -10,9 +12,20 @@ #ifndef __ASM_CPU_SH4_WATCHDOG_H #define __ASM_CPU_SH4_WATCHDOG_H +#if defined(CONFIG_CPU_SUBTYPE_SH7785) || defined(CONFIG_CPU_SUBTYPE_SH7780) +/* Prefix definition */ +#define WTBST_HIGH 0x55 +/* Register definitions */ +#define WTCNT_R 0xffcc0010 /*WDTCNT*/ +#define WTCSR 0xffcc0004 /*WDTCSR*/ +#define WTCNT 0xffcc0000 /*WDTST*/ +#define WTST WTCNT +#define WTBST 0xffcc0008 /*WDTBST*/ +#else /* Register definitions */ #define WTCNT 0xffc00008 #define WTCSR 0xffc0000c +#endif /* Bit definitions */ #define WTCSR_TME 0x80 diff --git a/arch/sh/include/mach-ecovec24/mach/partner-jet-setup.txt b/arch/sh/include/mach-ecovec24/mach/partner-jet-setup.txt index 8b8e4fa1fee9..cc737b807334 100644 --- a/arch/sh/include/mach-ecovec24/mach/partner-jet-setup.txt +++ b/arch/sh/include/mach-ecovec24/mach/partner-jet-setup.txt @@ -22,13 +22,12 @@ ED 0xff000010, 0x00000004 LIST "setup clocks" ED 0xa4150024, 0x00004000 ED 0xa4150000, 0x8E003508 -ED 0xa4150004, 0x00000000 WAIT 1 LIST "BSC" ED 0xff800020, 0xa5a50000 -ED 0xfec10000, 0x00000013 +ED 0xfec10000, 0x00001013 ED 0xfec10004, 0x11110400 ED 0xfec10024, 0x00000440 diff --git a/arch/sh/include/mach-se/mach/se7722.h b/arch/sh/include/mach-se/mach/se7722.h index e971d9a82f4a..16505bfb8a9e 100644 --- a/arch/sh/include/mach-se/mach/se7722.h +++ b/arch/sh/include/mach-se/mach/se7722.h @@ -92,18 +92,11 @@ #define SE7722_FPGA_IRQ_MRSHPC1 3 /* IRQ1 */ #define SE7722_FPGA_IRQ_MRSHPC2 4 /* IRQ1 */ #define SE7722_FPGA_IRQ_MRSHPC3 5 /* IRQ1 */ - #define SE7722_FPGA_IRQ_NR 6 -#define SE7722_FPGA_IRQ_BASE 110 - -#define MRSHPC_IRQ3 (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC3) -#define MRSHPC_IRQ2 (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC2) -#define MRSHPC_IRQ1 (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC1) -#define MRSHPC_IRQ0 (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC0) -#define SMC_IRQ (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_SMC) -#define USB_IRQ (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_USB) /* arch/sh/boards/se/7722/irq.c */ +extern unsigned int se7722_fpga_irq[]; + void init_se7722_IRQ(void); #define __IO_PREFIX se7722 diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index a2d0a40f3848..0471a3eb25ed 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -9,8 +9,12 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_ftrace.o = -pg endif -obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \ - machvec.o nmi_debug.o process_$(BITS).o ptrace_$(BITS).o \ +CFLAGS_REMOVE_return_address.o = -pg + +obj-y := debugtraps.o dma-nommu.o dumpstack.o \ + idle.o io.o io_generic.o irq.o \ + irq_$(BITS).o machvec.o nmi_debug.o process_$(BITS).o \ + ptrace_$(BITS).o return_address.o \ setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ syscalls_$(BITS).o time.o topology.o traps.o \ traps_$(BITS).o unwinder.o @@ -28,13 +32,13 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o +obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c index d218e808294e..08a2be775b6c 100644 --- a/arch/sh/kernel/asm-offsets.c +++ b/arch/sh/kernel/asm-offsets.c @@ -34,5 +34,28 @@ int main(void) DEFINE(PBE_NEXT, offsetof(struct pbe, next)); DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs)); #endif + + DEFINE(SH_SLEEP_MODE, offsetof(struct sh_sleep_data, mode)); + DEFINE(SH_SLEEP_SF_PRE, offsetof(struct sh_sleep_data, sf_pre)); + DEFINE(SH_SLEEP_SF_POST, offsetof(struct sh_sleep_data, sf_post)); + DEFINE(SH_SLEEP_RESUME, offsetof(struct sh_sleep_data, resume)); + DEFINE(SH_SLEEP_VBR, offsetof(struct sh_sleep_data, vbr)); + DEFINE(SH_SLEEP_SPC, offsetof(struct sh_sleep_data, spc)); + DEFINE(SH_SLEEP_SR, offsetof(struct sh_sleep_data, sr)); + DEFINE(SH_SLEEP_SP, offsetof(struct sh_sleep_data, sp)); + DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr)); + DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data)); + DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr)); + DEFINE(SH_SLEEP_REG_BAR, offsetof(struct sh_sleep_regs, bar)); + DEFINE(SH_SLEEP_REG_PTEH, offsetof(struct sh_sleep_regs, pteh)); + DEFINE(SH_SLEEP_REG_PTEL, offsetof(struct sh_sleep_regs, ptel)); + DEFINE(SH_SLEEP_REG_TTB, offsetof(struct sh_sleep_regs, ttb)); + DEFINE(SH_SLEEP_REG_TEA, offsetof(struct sh_sleep_regs, tea)); + DEFINE(SH_SLEEP_REG_MMUCR, offsetof(struct sh_sleep_regs, mmucr)); + DEFINE(SH_SLEEP_REG_PTEA, offsetof(struct sh_sleep_regs, ptea)); + DEFINE(SH_SLEEP_REG_PASCR, offsetof(struct sh_sleep_regs, pascr)); + DEFINE(SH_SLEEP_REG_IRMCR, offsetof(struct sh_sleep_regs, irmcr)); + DEFINE(SH_SLEEP_REG_CCR, offsetof(struct sh_sleep_regs, ccr)); + DEFINE(SH_SLEEP_REG_RAMCR, offsetof(struct sh_sleep_regs, ramcr)); return 0; } diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index 3d6b9312dc47..d97c803719ec 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/ # Common interfaces. -obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index e932ebef4738..89b4b76c0d76 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -75,16 +75,11 @@ static void __init expmask_init(void) /* * Future proofing. * - * Disable support for slottable sleep instruction - * and non-nop instructions in the rte delay slot. + * Disable support for slottable sleep instruction, non-nop + * instructions in the rte delay slot, and associative writes to + * the memory-mapped cache array. */ - expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP); - - /* - * Enable associative writes to the memory-mapped cache array - * until the cache flush ops have been rewritten. - */ - expmask |= EXPMASK_MMCAW; + expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP | EXPMASK_MMCAW); __raw_writel(expmask, EXPMASK); ctrl_barrier(); @@ -311,12 +306,12 @@ asmlinkage void __init sh_cpu_init(void) if (fpu_disabled) { printk("FPU Disabled\n"); current_cpu_data.flags &= ~CPU_HAS_FPU; - disable_fpu(); } /* FPU initialization */ + disable_fpu(); if ((current_cpu_data.flags & CPU_HAS_FPU)) { - clear_thread_flag(TIF_USEDFPU); + current_thread_info()->status &= ~TS_USEDFPU; clear_used_math(); } @@ -338,17 +333,6 @@ asmlinkage void __init sh_cpu_init(void) } #endif - /* - * Some brain-damaged loaders decided it would be a good idea to put - * the UBC to sleep. This causes some issues when it comes to things - * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So .. - * we wake it up and hope that all is well. - */ -#ifdef CONFIG_SUPERH32 - if (raw_smp_processor_id() == 0) - ubc_wakeup(); -#endif - speculative_execution_init(); expmask_init(); } diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index 6df2fb98eb30..d395ce5740e7 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c @@ -25,14 +25,12 @@ /* * Save FPU registers onto task structure. - * Assume called with FPU enabled (SR.FD=0). */ void -save_fpu(struct task_struct *tsk, struct pt_regs *regs) +save_fpu(struct task_struct *tsk) { unsigned long dummy; - clear_tsk_thread_flag(tsk, TIF_USEDFPU); enable_fpu(); asm volatile("sts.l fpul, @-%0\n\t" "sts.l fpscr, @-%0\n\t" @@ -60,7 +58,6 @@ save_fpu(struct task_struct *tsk, struct pt_regs *regs) : "memory"); disable_fpu(); - release_fpu(regs); } static void @@ -598,31 +595,31 @@ BUILD_TRAP_HANDLER(fpu_error) struct task_struct *tsk = current; TRAP_HANDLER_DECL; - save_fpu(tsk, regs); + __unlazy_fpu(tsk, regs); if (ieee_fpe_handler(regs)) { tsk->thread.fpu.hard.fpscr &= ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); grab_fpu(regs); restore_fpu(tsk); - set_tsk_thread_flag(tsk, TIF_USEDFPU); + task_thread_info(tsk)->status |= TS_USEDFPU; return; } force_sig(SIGFPE, tsk); } -BUILD_TRAP_HANDLER(fpu_state_restore) +void fpu_state_restore(struct pt_regs *regs) { struct task_struct *tsk = current; - TRAP_HANDLER_DECL; grab_fpu(regs); - if (!user_mode(regs)) { + if (unlikely(!user_mode(regs))) { printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); + BUG(); return; } - if (used_math()) { + if (likely(used_math())) { /* Using the FPU again. */ restore_fpu(tsk); } else { @@ -630,5 +627,13 @@ BUILD_TRAP_HANDLER(fpu_state_restore) fpu_init(); set_used_math(); } - set_tsk_thread_flag(tsk, TIF_USEDFPU); + task_thread_info(tsk)->status |= TS_USEDFPU; + tsk->fpu_counter++; +} + +BUILD_TRAP_HANDLER(fpu_state_restore) +{ + TRAP_HANDLER_DECL; + + fpu_state_restore(regs); } diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index bb407ef0b91e..3f7e2a22c7c2 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -297,41 +297,8 @@ ENTRY(vbr_base) ! .balign 256,0,256 general_exception: -#ifndef CONFIG_CPU_SUBTYPE_SHX3 bra handle_exception sts pr, k3 ! save original pr value in k3 -#else - mov.l 1f, k4 - mov.l @k4, k4 - - ! Is EXPEVT larger than 0x800? - mov #0x8, k0 - shll8 k0 - cmp/hs k0, k4 - bf 0f - - ! then add 0x580 (k2 is 0xd80 or 0xda0) - mov #0x58, k0 - shll2 k0 - shll2 k0 - add k0, k4 -0: - ! Setup stack and save DSP context (k0 contains original r15 on return) - bsr prepare_stack - nop - - ! Save registers / Switch to bank 0 - mov k4, k2 ! keep vector in k2 - mov.l 1f, k4 ! SR bits to clear in k4 - bsr save_regs ! needs original pr value in k3 - nop - - bra handle_exception_special - nop - - .align 2 -1: .long EXPEVT -#endif ! prepare_stack() ! - roll back gRB diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 203b18347b83..3a1dbc709831 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -9,6 +9,11 @@ obj-$(CONFIG_HIBERNATION) += $(addprefix ../sh3/, swsusp.o) obj-$(CONFIG_SH_FPU) += fpu.o softfloat.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o +# Perf events +perf-$(CONFIG_CPU_SUBTYPE_SH7750) := perf_event.o +perf-$(CONFIG_CPU_SUBTYPE_SH7750S) := perf_event.o +perf-$(CONFIG_CPU_SUBTYPE_SH7091) := perf_event.o + # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o @@ -27,4 +32,5 @@ endif # Additional clocks by subtype clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o -obj-y += $(clock-y) +obj-y += $(clock-y) +obj-$(CONFIG_PERF_EVENTS) += $(perf-y) diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index e3ea5411da6d..e97857aec8a0 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -41,13 +41,11 @@ static unsigned int fpu_exception_flags; /* * Save FPU registers onto task structure. - * Assume called with FPU enabled (SR.FD=0). */ -void save_fpu(struct task_struct *tsk, struct pt_regs *regs) +void save_fpu(struct task_struct *tsk) { unsigned long dummy; - clear_tsk_thread_flag(tsk, TIF_USEDFPU); enable_fpu(); asm volatile ("sts.l fpul, @-%0\n\t" "sts.l fpscr, @-%0\n\t" @@ -92,7 +90,6 @@ void save_fpu(struct task_struct *tsk, struct pt_regs *regs) :"memory"); disable_fpu(); - release_fpu(regs); } static void restore_fpu(struct task_struct *tsk) @@ -285,7 +282,6 @@ static int ieee_fpe_handler(struct pt_regs *regs) /* fcnvsd */ struct task_struct *tsk = current; - save_fpu(tsk, regs); if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)) /* FPU error */ denormal_to_double(&tsk->thread.fpu.hard, @@ -462,7 +458,7 @@ BUILD_TRAP_HANDLER(fpu_error) struct task_struct *tsk = current; TRAP_HANDLER_DECL; - save_fpu(tsk, regs); + __unlazy_fpu(tsk, regs); fpu_exception_flags = 0; if (ieee_fpe_handler(regs)) { tsk->thread.fpu.hard.fpscr &= @@ -473,7 +469,7 @@ BUILD_TRAP_HANDLER(fpu_error) tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10); grab_fpu(regs); restore_fpu(tsk); - set_tsk_thread_flag(tsk, TIF_USEDFPU); + task_thread_info(tsk)->status |= TS_USEDFPU; if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) & (fpu_exception_flags >> 2)) == 0) { return; @@ -483,18 +479,18 @@ BUILD_TRAP_HANDLER(fpu_error) force_sig(SIGFPE, tsk); } -BUILD_TRAP_HANDLER(fpu_state_restore) +void fpu_state_restore(struct pt_regs *regs) { struct task_struct *tsk = current; - TRAP_HANDLER_DECL; grab_fpu(regs); - if (!user_mode(regs)) { + if (unlikely(!user_mode(regs))) { printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); + BUG(); return; } - if (used_math()) { + if (likely(used_math())) { /* Using the FPU again. */ restore_fpu(tsk); } else { @@ -502,5 +498,13 @@ BUILD_TRAP_HANDLER(fpu_state_restore) fpu_init(); set_used_math(); } - set_tsk_thread_flag(tsk, TIF_USEDFPU); + task_thread_info(tsk)->status |= TS_USEDFPU; + tsk->fpu_counter++; +} + +BUILD_TRAP_HANDLER(fpu_state_restore) +{ + TRAP_HANDLER_DECL; + + fpu_state_restore(regs); } diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c new file mode 100644 index 000000000000..7f9ecc9c2d02 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/perf_event.c @@ -0,0 +1,253 @@ +/* + * Performance events support for SH7750-style performance counters + * + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/perf_event.h> +#include <asm/processor.h> + +#define PM_CR_BASE 0xff000084 /* 16-bit */ +#define PM_CTR_BASE 0xff100004 /* 32-bit */ + +#define PMCR(n) (PM_CR_BASE + ((n) * 0x04)) +#define PMCTRH(n) (PM_CTR_BASE + 0x00 + ((n) * 0x08)) +#define PMCTRL(n) (PM_CTR_BASE + 0x04 + ((n) * 0x08)) + +#define PMCR_PMM_MASK 0x0000003f + +#define PMCR_CLKF 0x00000100 +#define PMCR_PMCLR 0x00002000 +#define PMCR_PMST 0x00004000 +#define PMCR_PMEN 0x00008000 + +static struct sh_pmu sh7750_pmu; + +/* + * There are a number of events supported by each counter (33 in total). + * Since we have 2 counters, each counter will take the event code as it + * corresponds to the PMCR PMM setting. Each counter can be configured + * independently. + * + * Event Code Description + * ---------- ----------- + * + * 0x01 Operand read access + * 0x02 Operand write access + * 0x03 UTLB miss + * 0x04 Operand cache read miss + * 0x05 Operand cache write miss + * 0x06 Instruction fetch (w/ cache) + * 0x07 Instruction TLB miss + * 0x08 Instruction cache miss + * 0x09 All operand accesses + * 0x0a All instruction accesses + * 0x0b OC RAM operand access + * 0x0d On-chip I/O space access + * 0x0e Operand access (r/w) + * 0x0f Operand cache miss (r/w) + * 0x10 Branch instruction + * 0x11 Branch taken + * 0x12 BSR/BSRF/JSR + * 0x13 Instruction execution + * 0x14 Instruction execution in parallel + * 0x15 FPU Instruction execution + * 0x16 Interrupt + * 0x17 NMI + * 0x18 trapa instruction execution + * 0x19 UBCA match + * 0x1a UBCB match + * 0x21 Instruction cache fill + * 0x22 Operand cache fill + * 0x23 Elapsed time + * 0x24 Pipeline freeze by I-cache miss + * 0x25 Pipeline freeze by D-cache miss + * 0x27 Pipeline freeze by branch instruction + * 0x28 Pipeline freeze by CPU register + * 0x29 Pipeline freeze by FPU + */ + +static const int sh7750_general_events[] = { + [PERF_COUNT_HW_CPU_CYCLES] = 0x0023, + [PERF_COUNT_HW_INSTRUCTIONS] = 0x000a, + [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0006, /* I-cache */ + [PERF_COUNT_HW_CACHE_MISSES] = 0x0008, /* I-cache */ + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0010, + [PERF_COUNT_HW_BRANCH_MISSES] = -1, + [PERF_COUNT_HW_BUS_CYCLES] = -1, +}; + +#define C(x) PERF_COUNT_HW_CACHE_##x + +static const int sh7750_cache_events + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [ C(L1D) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0001, + [ C(RESULT_MISS) ] = 0x0004, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0x0002, + [ C(RESULT_MISS) ] = 0x0005, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(L1I) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0006, + [ C(RESULT_MISS) ] = 0x0008, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(LL) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(DTLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0x0003, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(ITLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0x0007, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, + + [ C(BPU) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, +}; + +static int sh7750_event_map(int event) +{ + return sh7750_general_events[event]; +} + +static u64 sh7750_pmu_read(int idx) +{ + return (u64)((u64)(__raw_readl(PMCTRH(idx)) & 0xffff) << 32) | + __raw_readl(PMCTRL(idx)); +} + +static void sh7750_pmu_disable(struct hw_perf_event *hwc, int idx) +{ + unsigned int tmp; + + tmp = __raw_readw(PMCR(idx)); + tmp &= ~(PMCR_PMM_MASK | PMCR_PMEN); + __raw_writew(tmp, PMCR(idx)); +} + +static void sh7750_pmu_enable(struct hw_perf_event *hwc, int idx) +{ + __raw_writew(__raw_readw(PMCR(idx)) | PMCR_PMCLR, PMCR(idx)); + __raw_writew(hwc->config | PMCR_PMEN | PMCR_PMST, PMCR(idx)); +} + +static void sh7750_pmu_disable_all(void) +{ + int i; + + for (i = 0; i < sh7750_pmu.num_events; i++) + __raw_writew(__raw_readw(PMCR(i)) & ~PMCR_PMEN, PMCR(i)); +} + +static void sh7750_pmu_enable_all(void) +{ + int i; + + for (i = 0; i < sh7750_pmu.num_events; i++) + __raw_writew(__raw_readw(PMCR(i)) | PMCR_PMEN, PMCR(i)); +} + +static struct sh_pmu sh7750_pmu = { + .name = "SH7750", + .num_events = 2, + .event_map = sh7750_event_map, + .max_events = ARRAY_SIZE(sh7750_general_events), + .raw_event_mask = PMCR_PMM_MASK, + .cache_events = &sh7750_cache_events, + .read = sh7750_pmu_read, + .disable = sh7750_pmu_disable, + .enable = sh7750_pmu_enable, + .disable_all = sh7750_pmu_disable_all, + .enable_all = sh7750_pmu_enable_all, +}; + +static int __init sh7750_pmu_init(void) +{ + /* + * Make sure this CPU actually has perf counters. + */ + if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) { + pr_notice("HW perf events unsupported, software events only.\n"); + return -ENODEV; + } + + return register_sh_pmu(&sh7750_pmu); +} +arch_initcall(sh7750_pmu_init); diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 490d5dc9e372..33bab477d2e2 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -44,3 +44,4 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o obj-y += $(clock-y) obj-$(CONFIG_SMP) += $(smp-y) obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) +obj-$(CONFIG_PERF_EVENTS) += perf_event.o diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index dfe9192be63e..9db743802f06 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -152,7 +152,7 @@ struct clk div6_clks[] = { SH_CLK_DIV6("fsia_clk", &div3_clk, FCLKACR, 0), SH_CLK_DIV6("fsib_clk", &div3_clk, FCLKBCR, 0), SH_CLK_DIV6("irda_clk", &div3_clk, IRDACLKCR, 0), - SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0), + SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT), }; #define R_CLK (&r_clk) diff --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c new file mode 100644 index 000000000000..eddc21973fa1 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/perf_event.c @@ -0,0 +1,269 @@ +/* + * Performance events support for SH-4A performance counters + * + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/perf_event.h> +#include <asm/processor.h> + +#define PPC_CCBR(idx) (0xff200800 + (sizeof(u32) * idx)) +#define PPC_PMCTR(idx) (0xfc100000 + (sizeof(u32) * idx)) + +#define CCBR_CIT_MASK (0x7ff << 6) +#define CCBR_DUC (1 << 3) +#define CCBR_CMDS (1 << 1) +#define CCBR_PPCE (1 << 0) + +#define PPC_PMCAT 0xfc100080 + +#define PMCAT_OVF3 (1 << 27) +#define PMCAT_CNN3 (1 << 26) +#define PMCAT_CLR3 (1 << 25) +#define PMCAT_OVF2 (1 << 19) +#define PMCAT_CLR2 (1 << 17) +#define PMCAT_OVF1 (1 << 11) +#define PMCAT_CNN1 (1 << 10) +#define PMCAT_CLR1 (1 << 9) +#define PMCAT_OVF0 (1 << 3) +#define PMCAT_CLR0 (1 << 1) + +static struct sh_pmu sh4a_pmu; + +/* + * Supported raw event codes: + * + * Event Code Description + * ---------- ----------- + * + * 0x0000 number of elapsed cycles + * 0x0200 number of elapsed cycles in privileged mode + * 0x0280 number of elapsed cycles while SR.BL is asserted + * 0x0202 instruction execution + * 0x0203 instruction execution in parallel + * 0x0204 number of unconditional branches + * 0x0208 number of exceptions + * 0x0209 number of interrupts + * 0x0220 UTLB miss caused by instruction fetch + * 0x0222 UTLB miss caused by operand access + * 0x02a0 number of ITLB misses + * 0x0028 number of accesses to instruction memories + * 0x0029 number of accesses to instruction cache + * 0x002a instruction cache miss + * 0x022e number of access to instruction X/Y memory + * 0x0030 number of reads to operand memories + * 0x0038 number of writes to operand memories + * 0x0031 number of operand cache read accesses + * 0x0039 number of operand cache write accesses + * 0x0032 operand cache read miss + * 0x003a operand cache write miss + * 0x0236 number of reads to operand X/Y memory + * 0x023e number of writes to operand X/Y memory + * 0x0237 number of reads to operand U memory + * 0x023f number of writes to operand U memory + * 0x0337 number of U memory read buffer misses + * 0x02b4 number of wait cycles due to operand read access + * 0x02bc number of wait cycles due to operand write access + * 0x0033 number of wait cycles due to operand cache read miss + * 0x003b number of wait cycles due to operand cache write miss + */ + +/* + * Special reserved bits used by hardware emulators, read values will + * vary, but writes must always be 0. + */ +#define PMCAT_EMU_CLR_MASK ((1 << 24) | (1 << 16) | (1 << 8) | (1 << 0)) + +static const int sh4a_general_events[] = { + [PERF_COUNT_HW_CPU_CYCLES] = 0x0000, + [PERF_COUNT_HW_INSTRUCTIONS] = 0x0202, + [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0029, /* I-cache */ + [PERF_COUNT_HW_CACHE_MISSES] = 0x002a, /* I-cache */ + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0204, + [PERF_COUNT_HW_BRANCH_MISSES] = -1, + [PERF_COUNT_HW_BUS_CYCLES] = -1, +}; + +#define C(x) PERF_COUNT_HW_CACHE_##x + +static const int sh4a_cache_events + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [ C(L1D) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0031, + [ C(RESULT_MISS) ] = 0x0032, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0x0039, + [ C(RESULT_MISS) ] = 0x003a, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(L1I) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0029, + [ C(RESULT_MISS) ] = 0x002a, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(LL) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0030, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0x0038, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(DTLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0222, + [ C(RESULT_MISS) ] = 0x0220, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + + [ C(ITLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0x02a0, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, + + [ C(BPU) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, +}; + +static int sh4a_event_map(int event) +{ + return sh4a_general_events[event]; +} + +static u64 sh4a_pmu_read(int idx) +{ + return __raw_readl(PPC_PMCTR(idx)); +} + +static void sh4a_pmu_disable(struct hw_perf_event *hwc, int idx) +{ + unsigned int tmp; + + tmp = __raw_readl(PPC_CCBR(idx)); + tmp &= ~(CCBR_CIT_MASK | CCBR_DUC); + __raw_writel(tmp, PPC_CCBR(idx)); +} + +static void sh4a_pmu_enable(struct hw_perf_event *hwc, int idx) +{ + unsigned int tmp; + + tmp = __raw_readl(PPC_PMCAT); + tmp &= ~PMCAT_EMU_CLR_MASK; + tmp |= idx ? PMCAT_CLR1 : PMCAT_CLR0; + __raw_writel(tmp, PPC_PMCAT); + + tmp = __raw_readl(PPC_CCBR(idx)); + tmp |= (hwc->config << 6) | CCBR_CMDS | CCBR_PPCE; + __raw_writel(tmp, PPC_CCBR(idx)); + + __raw_writel(__raw_readl(PPC_CCBR(idx)) | CCBR_DUC, PPC_CCBR(idx)); +} + +static void sh4a_pmu_disable_all(void) +{ + int i; + + for (i = 0; i < sh4a_pmu.num_events; i++) + __raw_writel(__raw_readl(PPC_CCBR(i)) & ~CCBR_DUC, PPC_CCBR(i)); +} + +static void sh4a_pmu_enable_all(void) +{ + int i; + + for (i = 0; i < sh4a_pmu.num_events; i++) + __raw_writel(__raw_readl(PPC_CCBR(i)) | CCBR_DUC, PPC_CCBR(i)); +} + +static struct sh_pmu sh4a_pmu = { + .name = "SH-4A", + .num_events = 2, + .event_map = sh4a_event_map, + .max_events = ARRAY_SIZE(sh4a_general_events), + .raw_event_mask = 0x3ff, + .cache_events = &sh4a_cache_events, + .read = sh4a_pmu_read, + .disable = sh4a_pmu_disable, + .enable = sh4a_pmu_enable, + .disable_all = sh4a_pmu_disable_all, + .enable_all = sh4a_pmu_enable_all, +}; + +static int __init sh4a_pmu_init(void) +{ + /* + * Make sure this CPU actually has perf counters. + */ + if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) { + pr_notice("HW perf events unsupported, software events only.\n"); + return -ENODEV; + } + + return register_sh_pmu(&sh4a_pmu); +} +arch_initcall(sh4a_pmu_init); diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index f3851fd757ec..845e89c936e7 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -20,6 +20,8 @@ #include <linux/uio_driver.h> #include <linux/sh_timer.h> #include <linux/io.h> +#include <linux/notifier.h> +#include <asm/suspend.h> #include <asm/clock.h> #include <asm/mmzone.h> #include <cpu/sh7724.h> @@ -202,7 +204,7 @@ static struct resource veu0_resources[] = { [0] = { .name = "VEU3F0", .start = 0xfe920000, - .end = 0xfe9200cb - 1, + .end = 0xfe9200cb, .flags = IORESOURCE_MEM, }, [1] = { @@ -234,7 +236,7 @@ static struct resource veu1_resources[] = { [0] = { .name = "VEU3F1", .start = 0xfe924000, - .end = 0xfe9240cb - 1, + .end = 0xfe9240cb, .flags = IORESOURCE_MEM, }, [1] = { @@ -523,6 +525,70 @@ static struct platform_device jpu_device = { }, }; +/* SPU2DSP0 */ +static struct uio_info spu0_platform_data = { + .name = "SPU2DSP0", + .version = "0", + .irq = 86, +}; + +static struct resource spu0_resources[] = { + [0] = { + .name = "SPU2DSP0", + .start = 0xFE200000, + .end = 0xFE2FFFFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device spu0_device = { + .name = "uio_pdrv_genirq", + .id = 4, + .dev = { + .platform_data = &spu0_platform_data, + }, + .resource = spu0_resources, + .num_resources = ARRAY_SIZE(spu0_resources), + .archdata = { + .hwblk_id = HWBLK_SPU, + }, +}; + +/* SPU2DSP1 */ +static struct uio_info spu1_platform_data = { + .name = "SPU2DSP1", + .version = "0", + .irq = 87, +}; + +static struct resource spu1_resources[] = { + [0] = { + .name = "SPU2DSP1", + .start = 0xFE300000, + .end = 0xFE3FFFFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device spu1_device = { + .name = "uio_pdrv_genirq", + .id = 5, + .dev = { + .platform_data = &spu1_platform_data, + }, + .resource = spu1_resources, + .num_resources = ARRAY_SIZE(spu1_resources), + .archdata = { + .hwblk_id = HWBLK_SPU, + }, +}; + static struct platform_device *sh7724_devices[] __initdata = { &cmt_device, &tmu0_device, @@ -539,6 +605,8 @@ static struct platform_device *sh7724_devices[] __initdata = { &veu0_device, &veu1_device, &jpu_device, + &spu0_device, + &spu1_device, }; static int __init sh7724_devices_setup(void) @@ -547,6 +615,8 @@ static int __init sh7724_devices_setup(void) platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20); platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20); + platform_resource_setup_memory(&spu0_device, "spu0", 2 << 20); + platform_resource_setup_memory(&spu1_device, "spu1", 2 << 20); return platform_add_devices(sh7724_devices, ARRAY_SIZE(sh7724_devices)); @@ -827,3 +897,193 @@ void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); } + +static struct { + /* BSC */ + unsigned long mmselr; + unsigned long cs0bcr; + unsigned long cs4bcr; + unsigned long cs5abcr; + unsigned long cs5bbcr; + unsigned long cs6abcr; + unsigned long cs6bbcr; + unsigned long cs4wcr; + unsigned long cs5awcr; + unsigned long cs5bwcr; + unsigned long cs6awcr; + unsigned long cs6bwcr; + /* INTC */ + unsigned short ipra; + unsigned short iprb; + unsigned short iprc; + unsigned short iprd; + unsigned short ipre; + unsigned short iprf; + unsigned short iprg; + unsigned short iprh; + unsigned short ipri; + unsigned short iprj; + unsigned short iprk; + unsigned short iprl; + unsigned char imr0; + unsigned char imr1; + unsigned char imr2; + unsigned char imr3; + unsigned char imr4; + unsigned char imr5; + unsigned char imr6; + unsigned char imr7; + unsigned char imr8; + unsigned char imr9; + unsigned char imr10; + unsigned char imr11; + unsigned char imr12; + /* RWDT */ + unsigned short rwtcnt; + unsigned short rwtcsr; + /* CPG */ + unsigned long irdaclk; + unsigned long spuclk; +} sh7724_rstandby_state; + +static int sh7724_pre_sleep_notifier_call(struct notifier_block *nb, + unsigned long flags, void *unused) +{ + if (!(flags & SUSP_SH_RSTANDBY)) + return NOTIFY_DONE; + + /* BCR */ + sh7724_rstandby_state.mmselr = __raw_readl(0xff800020); /* MMSELR */ + sh7724_rstandby_state.mmselr |= 0xa5a50000; + sh7724_rstandby_state.cs0bcr = __raw_readl(0xfec10004); /* CS0BCR */ + sh7724_rstandby_state.cs4bcr = __raw_readl(0xfec10010); /* CS4BCR */ + sh7724_rstandby_state.cs5abcr = __raw_readl(0xfec10014); /* CS5ABCR */ + sh7724_rstandby_state.cs5bbcr = __raw_readl(0xfec10018); /* CS5BBCR */ + sh7724_rstandby_state.cs6abcr = __raw_readl(0xfec1001c); /* CS6ABCR */ + sh7724_rstandby_state.cs6bbcr = __raw_readl(0xfec10020); /* CS6BBCR */ + sh7724_rstandby_state.cs4wcr = __raw_readl(0xfec10030); /* CS4WCR */ + sh7724_rstandby_state.cs5awcr = __raw_readl(0xfec10034); /* CS5AWCR */ + sh7724_rstandby_state.cs5bwcr = __raw_readl(0xfec10038); /* CS5BWCR */ + sh7724_rstandby_state.cs6awcr = __raw_readl(0xfec1003c); /* CS6AWCR */ + sh7724_rstandby_state.cs6bwcr = __raw_readl(0xfec10040); /* CS6BWCR */ + + /* INTC */ + sh7724_rstandby_state.ipra = __raw_readw(0xa4080000); /* IPRA */ + sh7724_rstandby_state.iprb = __raw_readw(0xa4080004); /* IPRB */ + sh7724_rstandby_state.iprc = __raw_readw(0xa4080008); /* IPRC */ + sh7724_rstandby_state.iprd = __raw_readw(0xa408000c); /* IPRD */ + sh7724_rstandby_state.ipre = __raw_readw(0xa4080010); /* IPRE */ + sh7724_rstandby_state.iprf = __raw_readw(0xa4080014); /* IPRF */ + sh7724_rstandby_state.iprg = __raw_readw(0xa4080018); /* IPRG */ + sh7724_rstandby_state.iprh = __raw_readw(0xa408001c); /* IPRH */ + sh7724_rstandby_state.ipri = __raw_readw(0xa4080020); /* IPRI */ + sh7724_rstandby_state.iprj = __raw_readw(0xa4080024); /* IPRJ */ + sh7724_rstandby_state.iprk = __raw_readw(0xa4080028); /* IPRK */ + sh7724_rstandby_state.iprl = __raw_readw(0xa408002c); /* IPRL */ + sh7724_rstandby_state.imr0 = __raw_readb(0xa4080080); /* IMR0 */ + sh7724_rstandby_state.imr1 = __raw_readb(0xa4080084); /* IMR1 */ + sh7724_rstandby_state.imr2 = __raw_readb(0xa4080088); /* IMR2 */ + sh7724_rstandby_state.imr3 = __raw_readb(0xa408008c); /* IMR3 */ + sh7724_rstandby_state.imr4 = __raw_readb(0xa4080090); /* IMR4 */ + sh7724_rstandby_state.imr5 = __raw_readb(0xa4080094); /* IMR5 */ + sh7724_rstandby_state.imr6 = __raw_readb(0xa4080098); /* IMR6 */ + sh7724_rstandby_state.imr7 = __raw_readb(0xa408009c); /* IMR7 */ + sh7724_rstandby_state.imr8 = __raw_readb(0xa40800a0); /* IMR8 */ + sh7724_rstandby_state.imr9 = __raw_readb(0xa40800a4); /* IMR9 */ + sh7724_rstandby_state.imr10 = __raw_readb(0xa40800a8); /* IMR10 */ + sh7724_rstandby_state.imr11 = __raw_readb(0xa40800ac); /* IMR11 */ + sh7724_rstandby_state.imr12 = __raw_readb(0xa40800b0); /* IMR12 */ + + /* RWDT */ + sh7724_rstandby_state.rwtcnt = __raw_readb(0xa4520000); /* RWTCNT */ + sh7724_rstandby_state.rwtcnt |= 0x5a00; + sh7724_rstandby_state.rwtcsr = __raw_readb(0xa4520004); /* RWTCSR */ + sh7724_rstandby_state.rwtcsr |= 0xa500; + __raw_writew(sh7724_rstandby_state.rwtcsr & 0x07, 0xa4520004); + + /* CPG */ + sh7724_rstandby_state.irdaclk = __raw_readl(0xa4150018); /* IRDACLKCR */ + sh7724_rstandby_state.spuclk = __raw_readl(0xa415003c); /* SPUCLKCR */ + + return NOTIFY_DONE; +} + +static int sh7724_post_sleep_notifier_call(struct notifier_block *nb, + unsigned long flags, void *unused) +{ + if (!(flags & SUSP_SH_RSTANDBY)) + return NOTIFY_DONE; + + /* BCR */ + __raw_writel(sh7724_rstandby_state.mmselr, 0xff800020); /* MMSELR */ + __raw_writel(sh7724_rstandby_state.cs0bcr, 0xfec10004); /* CS0BCR */ + __raw_writel(sh7724_rstandby_state.cs4bcr, 0xfec10010); /* CS4BCR */ + __raw_writel(sh7724_rstandby_state.cs5abcr, 0xfec10014); /* CS5ABCR */ + __raw_writel(sh7724_rstandby_state.cs5bbcr, 0xfec10018); /* CS5BBCR */ + __raw_writel(sh7724_rstandby_state.cs6abcr, 0xfec1001c); /* CS6ABCR */ + __raw_writel(sh7724_rstandby_state.cs6bbcr, 0xfec10020); /* CS6BBCR */ + __raw_writel(sh7724_rstandby_state.cs4wcr, 0xfec10030); /* CS4WCR */ + __raw_writel(sh7724_rstandby_state.cs5awcr, 0xfec10034); /* CS5AWCR */ + __raw_writel(sh7724_rstandby_state.cs5bwcr, 0xfec10038); /* CS5BWCR */ + __raw_writel(sh7724_rstandby_state.cs6awcr, 0xfec1003c); /* CS6AWCR */ + __raw_writel(sh7724_rstandby_state.cs6bwcr, 0xfec10040); /* CS6BWCR */ + + /* INTC */ + __raw_writew(sh7724_rstandby_state.ipra, 0xa4080000); /* IPRA */ + __raw_writew(sh7724_rstandby_state.iprb, 0xa4080004); /* IPRB */ + __raw_writew(sh7724_rstandby_state.iprc, 0xa4080008); /* IPRC */ + __raw_writew(sh7724_rstandby_state.iprd, 0xa408000c); /* IPRD */ + __raw_writew(sh7724_rstandby_state.ipre, 0xa4080010); /* IPRE */ + __raw_writew(sh7724_rstandby_state.iprf, 0xa4080014); /* IPRF */ + __raw_writew(sh7724_rstandby_state.iprg, 0xa4080018); /* IPRG */ + __raw_writew(sh7724_rstandby_state.iprh, 0xa408001c); /* IPRH */ + __raw_writew(sh7724_rstandby_state.ipri, 0xa4080020); /* IPRI */ + __raw_writew(sh7724_rstandby_state.iprj, 0xa4080024); /* IPRJ */ + __raw_writew(sh7724_rstandby_state.iprk, 0xa4080028); /* IPRK */ + __raw_writew(sh7724_rstandby_state.iprl, 0xa408002c); /* IPRL */ + __raw_writeb(sh7724_rstandby_state.imr0, 0xa4080080); /* IMR0 */ + __raw_writeb(sh7724_rstandby_state.imr1, 0xa4080084); /* IMR1 */ + __raw_writeb(sh7724_rstandby_state.imr2, 0xa4080088); /* IMR2 */ + __raw_writeb(sh7724_rstandby_state.imr3, 0xa408008c); /* IMR3 */ + __raw_writeb(sh7724_rstandby_state.imr4, 0xa4080090); /* IMR4 */ + __raw_writeb(sh7724_rstandby_state.imr5, 0xa4080094); /* IMR5 */ + __raw_writeb(sh7724_rstandby_state.imr6, 0xa4080098); /* IMR6 */ + __raw_writeb(sh7724_rstandby_state.imr7, 0xa408009c); /* IMR7 */ + __raw_writeb(sh7724_rstandby_state.imr8, 0xa40800a0); /* IMR8 */ + __raw_writeb(sh7724_rstandby_state.imr9, 0xa40800a4); /* IMR9 */ + __raw_writeb(sh7724_rstandby_state.imr10, 0xa40800a8); /* IMR10 */ + __raw_writeb(sh7724_rstandby_state.imr11, 0xa40800ac); /* IMR11 */ + __raw_writeb(sh7724_rstandby_state.imr12, 0xa40800b0); /* IMR12 */ + + /* RWDT */ + __raw_writew(sh7724_rstandby_state.rwtcnt, 0xa4520000); /* RWTCNT */ + __raw_writew(sh7724_rstandby_state.rwtcsr, 0xa4520004); /* RWTCSR */ + + /* CPG */ + __raw_writel(sh7724_rstandby_state.irdaclk, 0xa4150018); /* IRDACLKCR */ + __raw_writel(sh7724_rstandby_state.spuclk, 0xa415003c); /* SPUCLKCR */ + + return NOTIFY_DONE; +} + +static struct notifier_block sh7724_pre_sleep_notifier = { + .notifier_call = sh7724_pre_sleep_notifier_call, + .priority = SH_MOBILE_PRE(SH_MOBILE_SLEEP_CPU), +}; + +static struct notifier_block sh7724_post_sleep_notifier = { + .notifier_call = sh7724_post_sleep_notifier_call, + .priority = SH_MOBILE_POST(SH_MOBILE_SLEEP_CPU), +}; + +static int __init sh7724_sleep_setup(void) +{ + atomic_notifier_chain_register(&sh_mobile_pre_sleep_notifier_list, + &sh7724_pre_sleep_notifier); + + atomic_notifier_chain_register(&sh_mobile_post_sleep_notifier_list, + &sh7724_post_sleep_notifier); + return 0; +} +arch_initcall(sh7724_sleep_setup); + diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c index e848443deeb9..c7ba9166e18a 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c @@ -15,6 +15,15 @@ #include <linux/sh_timer.h> #include <asm/mmzone.h> +/* + * This intentionally only registers SCIF ports 0, 1, and 3. SCIF 2 + * INTEVT values overlap with the FPU EXPEVT ones, requiring special + * demuxing in the exception dispatch path. + * + * As this overlap is something that never should have made it in to + * silicon in the first place, we just refuse to deal with the port at + * all rather than adding infrastructure to hack around it. + */ static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffc30000, @@ -27,11 +36,6 @@ static struct plat_sci_port sci_platform_data[] = { .type = PORT_SCIF, .irqs = { 44, 45, 47, 46 }, }, { - .mapbase = 0xffc50000, - .flags = UPF_BOOT_AUTOCONF, - .type = PORT_SCIF, - .irqs = { 48, 49, 51, 50 }, - }, { .mapbase = 0xffc60000, .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, @@ -268,7 +272,11 @@ enum { UNUSED = 0, /* interrupt sources */ - IRL, IRQ0, IRQ1, IRQ2, IRQ3, + IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, + IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, + IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, + IRL_HHLL, IRL_HHLH, IRL_HHHL, + IRQ0, IRQ1, IRQ2, IRQ3, HUDII, TMU0, TMU1, TMU2, TMU3, TMU4, TMU5, PCII0, PCII1, PCII2, PCII3, PCII4, @@ -291,7 +299,7 @@ enum { INTICI4, INTICI5, INTICI6, INTICI7, /* interrupt groups */ - PCII56789, SCIF0, SCIF1, SCIF2, SCIF3, + IRL, PCII56789, SCIF0, SCIF1, SCIF2, SCIF3, DMAC0, DMAC1, }; @@ -309,8 +317,6 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760), INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0), INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0), - INTC_VECT(SCIF2_ERI, 0x800), INTC_VECT(SCIF2_RXI, 0x820), - INTC_VECT(SCIF2_BRI, 0x840), INTC_VECT(SCIF2_TXI, 0x860), INTC_VECT(SCIF3_ERI, 0x880), INTC_VECT(SCIF3_RXI, 0x8a0), INTC_VECT(SCIF3_BRI, 0x8c0), INTC_VECT(SCIF3_TXI, 0x8e0), INTC_VECT(DMAC0_DMINT0, 0x900), INTC_VECT(DMAC0_DMINT1, 0x920), @@ -344,10 +350,13 @@ static struct intc_vect vectors[] __initdata = { }; static struct intc_group groups[] __initdata = { + INTC_GROUP(IRL, IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, + IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, + IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, + IRL_HHLL, IRL_HHLH, IRL_HHHL), INTC_GROUP(PCII56789, PCII5, PCII6, PCII7, PCII8, PCII9), INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI), INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI), - INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI), INTC_GROUP(SCIF3, SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI), INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE), @@ -419,14 +428,14 @@ static DECLARE_INTC_DESC(intc_desc_irq, "shx3-irq", vectors_irq, groups, /* External interrupt pins in IRL mode */ static struct intc_vect vectors_irl[] __initdata = { - INTC_VECT(IRL, 0x200), INTC_VECT(IRL, 0x220), - INTC_VECT(IRL, 0x240), INTC_VECT(IRL, 0x260), - INTC_VECT(IRL, 0x280), INTC_VECT(IRL, 0x2a0), - INTC_VECT(IRL, 0x2c0), INTC_VECT(IRL, 0x2e0), - INTC_VECT(IRL, 0x300), INTC_VECT(IRL, 0x320), - INTC_VECT(IRL, 0x340), INTC_VECT(IRL, 0x360), - INTC_VECT(IRL, 0x380), INTC_VECT(IRL, 0x3a0), - INTC_VECT(IRL, 0x3c0), + INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220), + INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260), + INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0), + INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0), + INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320), + INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360), + INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0), + INTC_VECT(IRL_HHHL, 0x3c0), }; static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups, diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 185ec3976a25..5863e0c4d02f 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -14,6 +14,13 @@ #include <linux/interrupt.h> #include <linux/io.h> +#define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) +#define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) + +#define STBCR_MSTP 0x00000001 +#define STBCR_RESET 0x00000002 +#define STBCR_LTSLP 0x80000000 + static irqreturn_t ipi_interrupt_handler(int irq, void *arg) { unsigned int message = (unsigned int)(long)arg; @@ -21,9 +28,9 @@ static irqreturn_t ipi_interrupt_handler(int irq, void *arg) unsigned int offs = 4 * cpu; unsigned int x; - x = ctrl_inl(0xfe410070 + offs); /* C0INITICI..CnINTICI */ + x = __raw_readl(0xfe410070 + offs); /* C0INITICI..CnINTICI */ x &= (1 << (message << 2)); - ctrl_outl(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */ + __raw_writel(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */ smp_message_recv(message); @@ -37,6 +44,9 @@ void __init plat_smp_setup(void) init_cpu_possible(cpumask_of(cpu)); + /* Enable light sleep for the boot CPU */ + __raw_writel(__raw_readl(STBCR_REG(cpu)) | STBCR_LTSLP, STBCR_REG(cpu)); + __cpu_number_map[0] = 0; __cpu_logical_map[0] = 0; @@ -66,32 +76,23 @@ void __init plat_prepare_cpus(unsigned int max_cpus) "IPI", (void *)(long)i); } -#define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) -#define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) - -#define STBCR_MSTP 0x00000001 -#define STBCR_RESET 0x00000002 -#define STBCR_LTSLP 0x80000000 - -#define STBCR_AP_VAL (STBCR_RESET | STBCR_LTSLP) - void plat_start_cpu(unsigned int cpu, unsigned long entry_point) { - ctrl_outl(entry_point, RESET_REG(cpu)); + __raw_writel(entry_point, RESET_REG(cpu)); - if (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP)) - ctrl_outl(STBCR_MSTP, STBCR_REG(cpu)); + if (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP)) + __raw_writel(STBCR_MSTP, STBCR_REG(cpu)); - while (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP)) + while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP)) cpu_relax(); /* Start up secondary processor by sending a reset */ - ctrl_outl(STBCR_AP_VAL, STBCR_REG(cpu)); + __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu)); } int plat_smp_processor_id(void) { - return ctrl_inl(0xff000048); /* CPIDR */ + return __raw_readl(0xff000048); /* CPIDR */ } void plat_send_ipi(unsigned int cpu, unsigned int message) @@ -100,5 +101,5 @@ void plat_send_ipi(unsigned int cpu, unsigned int message) BUG_ON(cpu >= 4); - ctrl_outl(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ + __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ } diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index b0aacf675258..8f13f73cb2cb 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -933,7 +933,7 @@ ret_with_reschedule: pta restore_all, tr1 - movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8 + movi _TIF_SIGPENDING, r8 and r8, r7, r8 pta work_notifysig, tr0 bne r8, ZERO, tr0 diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index 1c504bd972c3..83972aa319c2 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c @@ -87,25 +87,31 @@ void sh_mobile_setup_cpuidle(void) dev->safe_state = state; - state = &dev->states[i++]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); - strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN); - state->exit_latency = 100; - state->target_residency = 1 * 2; - state->power_usage = 1; - state->flags = 0; - state->flags |= CPUIDLE_FLAG_TIME_VALID; - state->enter = cpuidle_sleep_enter; + if (sh_mobile_sleep_supported & SUSP_SH_SF) { + state = &dev->states[i++]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); + strncpy(state->desc, "SuperH Sleep Mode [SF]", + CPUIDLE_DESC_LEN); + state->exit_latency = 100; + state->target_residency = 1 * 2; + state->power_usage = 1; + state->flags = 0; + state->flags |= CPUIDLE_FLAG_TIME_VALID; + state->enter = cpuidle_sleep_enter; + } - state = &dev->states[i++]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); - strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", CPUIDLE_DESC_LEN); - state->exit_latency = 2300; - state->target_residency = 1 * 2; - state->power_usage = 1; - state->flags = 0; - state->flags |= CPUIDLE_FLAG_TIME_VALID; - state->enter = cpuidle_sleep_enter; + if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) { + state = &dev->states[i++]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); + strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", + CPUIDLE_DESC_LEN); + state->exit_latency = 2300; + state->target_residency = 1 * 2; + state->power_usage = 1; + state->flags = 0; + state->flags |= CPUIDLE_FLAG_TIME_VALID; + state->enter = cpuidle_sleep_enter; + } dev->state_count = i; diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c index ee3c2aaf66fb..ca029a44743c 100644 --- a/arch/sh/kernel/cpu/shmobile/pm.c +++ b/arch/sh/kernel/cpu/shmobile/pm.c @@ -15,6 +15,13 @@ #include <linux/suspend.h> #include <asm/suspend.h> #include <asm/uaccess.h> +#include <asm/cacheflush.h> + +/* + * Notifier lists for pre/post sleep notification + */ +ATOMIC_NOTIFIER_HEAD(sh_mobile_pre_sleep_notifier_list); +ATOMIC_NOTIFIER_HEAD(sh_mobile_post_sleep_notifier_list); /* * Sleep modes available on SuperH Mobile: @@ -26,30 +33,105 @@ #define SUSP_MODE_SLEEP (SUSP_SH_SLEEP) #define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF) #define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF) +#define SUSP_MODE_RSTANDBY (SUSP_SH_RSTANDBY | SUSP_SH_MMU | SUSP_SH_SF) + /* + * U-standby mode is unsupported since it needs bootloader hacks + */ -/* - * The following modes are not there yet: - * - * R-standby mode is unsupported, but will be added in the future - * U-standby mode is low priority since it needs bootloader hacks - */ - -#define ILRAM_BASE 0xe5200000 - -extern const unsigned char sh_mobile_standby[]; -extern const unsigned int sh_mobile_standby_size; +#ifdef CONFIG_CPU_SUBTYPE_SH7724 +#define RAM_BASE 0xfd800000 /* RSMEM */ +#else +#define RAM_BASE 0xe5200000 /* ILRAM */ +#endif void sh_mobile_call_standby(unsigned long mode) { - void *onchip_mem = (void *)ILRAM_BASE; - void (*standby_onchip_mem)(unsigned long, unsigned long) = onchip_mem; + void *onchip_mem = (void *)RAM_BASE; + struct sh_sleep_data *sdp = onchip_mem; + void (*standby_onchip_mem)(unsigned long, unsigned long); + + /* code located directly after data structure */ + standby_onchip_mem = (void *)(sdp + 1); + + atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list, + mode, NULL); + + /* flush the caches if MMU flag is set */ + if (mode & SUSP_SH_MMU) + flush_cache_all(); /* Let assembly snippet in on-chip memory handle the rest */ - standby_onchip_mem(mode, ILRAM_BASE); + standby_onchip_mem(mode, RAM_BASE); + + atomic_notifier_call_chain(&sh_mobile_post_sleep_notifier_list, + mode, NULL); +} + +extern char sh_mobile_sleep_enter_start; +extern char sh_mobile_sleep_enter_end; + +extern char sh_mobile_sleep_resume_start; +extern char sh_mobile_sleep_resume_end; + +unsigned long sh_mobile_sleep_supported = SUSP_SH_SLEEP; + +void sh_mobile_register_self_refresh(unsigned long flags, + void *pre_start, void *pre_end, + void *post_start, void *post_end) +{ + void *onchip_mem = (void *)RAM_BASE; + void *vp; + struct sh_sleep_data *sdp; + int n; + + /* part 0: data area */ + sdp = onchip_mem; + sdp->addr.stbcr = 0xa4150020; /* STBCR */ + sdp->addr.bar = 0xa4150040; /* BAR */ + sdp->addr.pteh = 0xff000000; /* PTEH */ + sdp->addr.ptel = 0xff000004; /* PTEL */ + sdp->addr.ttb = 0xff000008; /* TTB */ + sdp->addr.tea = 0xff00000c; /* TEA */ + sdp->addr.mmucr = 0xff000010; /* MMUCR */ + sdp->addr.ptea = 0xff000034; /* PTEA */ + sdp->addr.pascr = 0xff000070; /* PASCR */ + sdp->addr.irmcr = 0xff000078; /* IRMCR */ + sdp->addr.ccr = 0xff00001c; /* CCR */ + sdp->addr.ramcr = 0xff000074; /* RAMCR */ + vp = sdp + 1; + + /* part 1: common code to enter sleep mode */ + n = &sh_mobile_sleep_enter_end - &sh_mobile_sleep_enter_start; + memcpy(vp, &sh_mobile_sleep_enter_start, n); + vp += roundup(n, 4); + + /* part 2: board specific code to enter self-refresh mode */ + n = pre_end - pre_start; + memcpy(vp, pre_start, n); + sdp->sf_pre = (unsigned long)vp; + vp += roundup(n, 4); + + /* part 3: board specific code to resume from self-refresh mode */ + n = post_end - post_start; + memcpy(vp, post_start, n); + sdp->sf_post = (unsigned long)vp; + vp += roundup(n, 4); + + /* part 4: common code to resume from sleep mode */ + WARN_ON(vp > (onchip_mem + 0x600)); + vp = onchip_mem + 0x600; /* located at interrupt vector */ + n = &sh_mobile_sleep_resume_end - &sh_mobile_sleep_resume_start; + memcpy(vp, &sh_mobile_sleep_resume_start, n); + sdp->resume = (unsigned long)vp; + + sh_mobile_sleep_supported |= flags; } static int sh_pm_enter(suspend_state_t state) { + if (!(sh_mobile_sleep_supported & SUSP_MODE_STANDBY_SF)) + return -ENXIO; + local_irq_disable(); set_bl_bit(); sh_mobile_call_standby(SUSP_MODE_STANDBY_SF); @@ -65,13 +147,6 @@ static struct platform_suspend_ops sh_pm_ops = { static int __init sh_pm_init(void) { - void *onchip_mem = (void *)ILRAM_BASE; - - /* Copy the assembly snippet to the otherwise ununsed ILRAM */ - memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size); - wmb(); - ctrl_barrier(); - suspend_set_ops(&sh_pm_ops); sh_mobile_setup_cpuidle(); return 0; diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c index 7c615b17e209..6dcb8166a64d 100644 --- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c +++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c @@ -45,12 +45,14 @@ static int __platform_pm_runtime_resume(struct platform_device *pdev) dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk); - if (d->driver && d->driver->pm && d->driver->pm->runtime_resume) { + if (d->driver) { hwblk_enable(hwblk_info, hwblk); ret = 0; if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) { - ret = d->driver->pm->runtime_resume(d); + if (d->driver->pm && d->driver->pm->runtime_resume) + ret = d->driver->pm->runtime_resume(d); + if (!ret) clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); else @@ -73,12 +75,15 @@ static int __platform_pm_runtime_suspend(struct platform_device *pdev) dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk); - if (d->driver && d->driver->pm && d->driver->pm->runtime_suspend) { + if (d->driver) { BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags)); + ret = 0; - hwblk_enable(hwblk_info, hwblk); - ret = d->driver->pm->runtime_suspend(d); - hwblk_disable(hwblk_info, hwblk); + if (d->driver->pm && d->driver->pm->runtime_suspend) { + hwblk_enable(hwblk_info, hwblk); + ret = d->driver->pm->runtime_suspend(d); + hwblk_disable(hwblk_info, hwblk); + } if (!ret) { set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S index a439e6c7824f..e9dd7fa0abd2 100644 --- a/arch/sh/kernel/cpu/shmobile/sleep.S +++ b/arch/sh/kernel/cpu/shmobile/sleep.S @@ -20,79 +20,103 @@ * Kernel mode register usage, see entry.S: * k0 scratch * k1 scratch - * k4 scratch */ #define k0 r0 #define k1 r1 -#define k4 r4 -/* manage self-refresh and enter standby mode. +/* manage self-refresh and enter standby mode. must be self-contained. * this code will be copied to on-chip memory and executed from there. */ + .balign 4 +ENTRY(sh_mobile_sleep_enter_start) - .balign 4096,0,4096 -ENTRY(sh_mobile_standby) + /* save mode flags */ + mov.l r4, @(SH_SLEEP_MODE, r5) /* save original vbr */ - stc vbr, r1 - mova saved_vbr, r0 - mov.l r1, @r0 + stc vbr, r0 + mov.l r0, @(SH_SLEEP_VBR, r5) /* point vbr to our on-chip memory page */ ldc r5, vbr /* save return address */ - mova saved_spc, r0 - sts pr, r5 - mov.l r5, @r0 + sts pr, r0 + mov.l r0, @(SH_SLEEP_SPC, r5) /* save sr */ - mova saved_sr, r0 - stc sr, r5 - mov.l r5, @r0 + stc sr, r0 + mov.l r0, @(SH_SLEEP_SR, r5) - /* save mode flags */ - mova saved_mode, r0 - mov.l r4, @r0 + /* save sp */ + mov.l r15, @(SH_SLEEP_SP, r5) + + /* save stbcr */ + bsr save_register + mov #SH_SLEEP_REG_STBCR, r0 + + /* save mmu and cache context if needed */ + mov.l @(SH_SLEEP_MODE, r5), r0 + tst #SUSP_SH_MMU, r0 + bt skip_mmu_save_disable + + /* save mmu state */ + bsr save_register + mov #SH_SLEEP_REG_PTEH, r0 + + bsr save_register + mov #SH_SLEEP_REG_PTEL, r0 + + bsr save_register + mov #SH_SLEEP_REG_TTB, r0 + + bsr save_register + mov #SH_SLEEP_REG_TEA, r0 + + bsr save_register + mov #SH_SLEEP_REG_MMUCR, r0 + + bsr save_register + mov #SH_SLEEP_REG_PTEA, r0 + + bsr save_register + mov #SH_SLEEP_REG_PASCR, r0 - /* put mode flags in r0 */ - mov r4, r0 + bsr save_register + mov #SH_SLEEP_REG_IRMCR, r0 + /* invalidate TLBs and disable the MMU */ + bsr get_register + mov #SH_SLEEP_REG_MMUCR, r0 + mov #4, r1 + mov.l r1, @r0 + icbi @r0 + + /* save cache registers and disable caches */ + bsr save_register + mov #SH_SLEEP_REG_CCR, r0 + + bsr save_register + mov #SH_SLEEP_REG_RAMCR, r0 + + bsr get_register + mov #SH_SLEEP_REG_CCR, r0 + mov #0, r1 + mov.l r1, @r0 + icbi @r0 + +skip_mmu_save_disable: + /* call self-refresh entering code if needed */ + mov.l @(SH_SLEEP_MODE, r5), r0 tst #SUSP_SH_SF, r0 bt skip_set_sf -#ifdef CONFIG_CPU_SUBTYPE_SH7724 - /* DBSC: put memory in self-refresh mode */ - mov.l dben_reg, r4 - mov.l dben_data0, r1 - mov.l r1, @r4 - - mov.l dbrfpdn0_reg, r4 - mov.l dbrfpdn0_data0, r1 - mov.l r1, @r4 - - mov.l dbcmdcnt_reg, r4 - mov.l dbcmdcnt_data0, r1 - mov.l r1, @r4 - - mov.l dbcmdcnt_reg, r4 - mov.l dbcmdcnt_data1, r1 - mov.l r1, @r4 - - mov.l dbrfpdn0_reg, r4 - mov.l dbrfpdn0_data1, r1 - mov.l r1, @r4 -#else - /* SBSC: disable power down and put in self-refresh mode */ - mov.l 1f, r4 - mov.l 2f, r1 - mov.l @r4, r2 - or r1, r2 - mov.l 3f, r3 - and r3, r2 - mov.l r2, @r4 -#endif + + mov.l @(SH_SLEEP_SF_PRE, r5), r0 + jsr @r0 + nop skip_set_sf: + mov.l @(SH_SLEEP_MODE, r5), r0 tst #SUSP_SH_STANDBY, r0 bt test_rstandby @@ -104,6 +128,12 @@ test_rstandby: tst #SUSP_SH_RSTANDBY, r0 bt test_ustandby + /* setup BAR register */ + bsr get_register + mov #SH_SLEEP_REG_BAR, r0 + mov.l @(SH_SLEEP_RESUME, r5), r1 + mov.l r1, @r0 + /* set mode to "r-standby mode" */ bra do_sleep mov #0x20, r1 @@ -123,124 +153,136 @@ force_sleep: do_sleep: /* setup and enter selected standby mode */ - mov.l 5f, r4 - mov.l r1, @r4 + bsr get_register + mov #SH_SLEEP_REG_STBCR, r0 + mov.l r1, @r0 again: sleep bra again nop -restore_jump_vbr: +save_register: + add #SH_SLEEP_BASE_ADDR, r0 + mov.l @(r0, r5), r1 + add #-SH_SLEEP_BASE_ADDR, r0 + mov.l @r1, r1 + add #SH_SLEEP_BASE_DATA, r0 + mov.l r1, @(r0, r5) + add #-SH_SLEEP_BASE_DATA, r0 + rts + nop + +get_register: + add #SH_SLEEP_BASE_ADDR, r0 + mov.l @(r0, r5), r0 + rts + nop +ENTRY(sh_mobile_sleep_enter_end) + + .balign 4 +ENTRY(sh_mobile_sleep_resume_start) + + /* figure out start address */ + bsr 0f + nop +0: + sts pr, k1 + mov.l 1f, k0 + and k0, k1 + + /* store pointer to data area in VBR */ + ldc k1, vbr + + /* setup sr with saved sr */ + mov.l @(SH_SLEEP_SR, k1), k0 + ldc k0, sr + + /* now: user register set! */ + stc vbr, r5 + /* setup spc with return address to c code */ - mov.l saved_spc, k0 - ldc k0, spc + mov.l @(SH_SLEEP_SPC, r5), r0 + ldc r0, spc /* restore vbr */ - mov.l saved_vbr, k0 - ldc k0, vbr + mov.l @(SH_SLEEP_VBR, r5), r0 + ldc r0, vbr /* setup ssr with saved sr */ - mov.l saved_sr, k0 - ldc k0, ssr + mov.l @(SH_SLEEP_SR, r5), r0 + ldc r0, ssr - /* get mode flags */ - mov.l saved_mode, k0 + /* restore sp */ + mov.l @(SH_SLEEP_SP, r5), r15 -done_sleep: - /* reset standby mode to sleep mode */ - mov.l 5f, k4 - mov #0x00, k1 - mov.l k1, @k4 + /* restore sleep mode register */ + bsr restore_register + mov #SH_SLEEP_REG_STBCR, r0 - tst #SUSP_SH_SF, k0 + /* call self-refresh resume code if needed */ + mov.l @(SH_SLEEP_MODE, r5), r0 + tst #SUSP_SH_SF, r0 bt skip_restore_sf -#ifdef CONFIG_CPU_SUBTYPE_SH7724 - /* DBSC: put memory in auto-refresh mode */ - mov.l dbrfpdn0_reg, k4 - mov.l dbrfpdn0_data0, k1 - mov.l k1, @k4 - - nop /* sleep 140 ns */ - nop - nop - nop - - mov.l dbcmdcnt_reg, k4 - mov.l dbcmdcnt_data0, k1 - mov.l k1, @k4 - - mov.l dbcmdcnt_reg, k4 - mov.l dbcmdcnt_data1, k1 - mov.l k1, @k4 - - mov.l dben_reg, k4 - mov.l dben_data1, k1 - mov.l k1, @k4 - - mov.l dbrfpdn0_reg, k4 - mov.l dbrfpdn0_data2, k1 - mov.l k1, @k4 -#else - /* SBSC: set auto-refresh mode */ - mov.l 1f, k4 - mov.l @k4, k0 - mov.l 4f, k1 - and k1, k0 - mov.l k0, @k4 - mov.l 6f, k4 - mov.l 8f, k0 - mov.l @k4, k1 - mov #-1, k4 - add k4, k1 - or k1, k0 - mov.l 7f, k1 - mov.l k0, @k1 -#endif + mov.l @(SH_SLEEP_SF_POST, r5), r0 + jsr @r0 + nop + skip_restore_sf: - /* jump to vbr vector */ - mov.l saved_vbr, k0 - mov.l offset_vbr, k4 - add k4, k0 - jmp @k0 + /* restore mmu and cache state if needed */ + mov.l @(SH_SLEEP_MODE, r5), r0 + tst #SUSP_SH_MMU, r0 + bt skip_restore_mmu + + /* restore mmu state */ + bsr restore_register + mov #SH_SLEEP_REG_PTEH, r0 + + bsr restore_register + mov #SH_SLEEP_REG_PTEL, r0 + + bsr restore_register + mov #SH_SLEEP_REG_TTB, r0 + + bsr restore_register + mov #SH_SLEEP_REG_TEA, r0 + + bsr restore_register + mov #SH_SLEEP_REG_PTEA, r0 + + bsr restore_register + mov #SH_SLEEP_REG_PASCR, r0 + + bsr restore_register + mov #SH_SLEEP_REG_IRMCR, r0 + + bsr restore_register + mov #SH_SLEEP_REG_MMUCR, r0 + icbi @r0 + + /* restore cache settings */ + bsr restore_register + mov #SH_SLEEP_REG_RAMCR, r0 + icbi @r0 + + bsr restore_register + mov #SH_SLEEP_REG_CCR, r0 + icbi @r0 + +skip_restore_mmu: + rte nop - .balign 4 -saved_mode: .long 0 -saved_spc: .long 0 -saved_sr: .long 0 -saved_vbr: .long 0 -offset_vbr: .long 0x600 -#ifdef CONFIG_CPU_SUBTYPE_SH7724 -dben_reg: .long 0xfd000010 /* DBEN */ -dben_data0: .long 0 -dben_data1: .long 1 -dbrfpdn0_reg: .long 0xfd000040 /* DBRFPDN0 */ -dbrfpdn0_data0: .long 0 -dbrfpdn0_data1: .long 1 -dbrfpdn0_data2: .long 0x00010000 -dbcmdcnt_reg: .long 0xfd000014 /* DBCMDCNT */ -dbcmdcnt_data0: .long 2 -dbcmdcnt_data1: .long 4 -#else -1: .long 0xfe400008 /* SDCR0 */ -2: .long 0x00000400 -3: .long 0xffff7fff -4: .long 0xfffffbff -#endif -5: .long 0xa4150020 /* STBCR */ -6: .long 0xfe40001c /* RTCOR */ -7: .long 0xfe400018 /* RTCNT */ -8: .long 0xa55a0000 - - -/* interrupt vector @ 0x600 */ - .balign 0x400,0,0x400 - .long 0xdeadbeef - .balign 0x200,0,0x200 - bra restore_jump_vbr +restore_register: + add #SH_SLEEP_BASE_DATA, r0 + mov.l @(r0, r5), r1 + add #-SH_SLEEP_BASE_DATA, r0 + add #SH_SLEEP_BASE_ADDR, r0 + mov.l @(r0, r5), r0 + mov.l r1, @r0 + rts nop -sh_mobile_standby_end: -ENTRY(sh_mobile_standby_size) - .long sh_mobile_standby_end - sh_mobile_standby + .balign 4 +1: .long ~0x7ff +ENTRY(sh_mobile_sleep_resume_end) diff --git a/arch/sh/kernel/cpu/ubc.S b/arch/sh/kernel/cpu/ubc.S deleted file mode 100644 index 81923079fa12..000000000000 --- a/arch/sh/kernel/cpu/ubc.S +++ /dev/null @@ -1,59 +0,0 @@ -/* - * arch/sh/kernel/cpu/ubc.S - * - * Set of management routines for the User Break Controller (UBC) - * - * Copyright (C) 2002 Paul Mundt - * - * 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/linkage.h> -#include <asm/ubc.h> - -#define STBCR2 0xffc00010 - -ENTRY(ubc_sleep) - mov #0, r0 - - mov.l 1f, r1 ! Zero out UBC_BBRA .. - mov.w r0, @r1 - - mov.l 2f, r1 ! .. same for BBRB .. - mov.w r0, @r1 - - mov.l 3f, r1 ! .. and again for BRCR. - mov.w r0, @r1 - - mov.w @r1, r0 ! Dummy read BRCR - - mov.l 4f, r1 ! Set MSTP5 in STBCR2 - mov.b @r1, r0 - or #0x01, r0 - mov.b r0, @r1 - - mov.b @r1, r0 ! Two dummy reads .. - mov.b @r1, r0 - - rts - nop - -ENTRY(ubc_wakeup) - mov.l 4f, r1 ! Clear MSTP5 - mov.b @r1, r0 - and #0xfe, r0 - mov.b r0, @r1 - - mov.b @r1, r0 ! Two more dummy reads .. - mov.b @r1, r0 - - rts - nop - -1: .long UBC_BBRA -2: .long UBC_BBRB -3: .long UBC_BRCR -4: .long STBCR2 - diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c new file mode 100644 index 000000000000..3c55b87f8b63 --- /dev/null +++ b/arch/sh/kernel/dma-nommu.c @@ -0,0 +1,82 @@ +/* + * DMA mapping support for platforms lacking IOMMUs. + * + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/dma-mapping.h> +#include <linux/io.h> + +static dma_addr_t nommu_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + dma_addr_t addr = page_to_phys(page) + offset; + + WARN_ON(size == 0); + dma_cache_sync(dev, page_address(page) + offset, size, dir); + + return addr; +} + +static int nommu_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + struct scatterlist *s; + int i; + + WARN_ON(nents == 0 || sg[0].length == 0); + + for_each_sg(sg, s, nents, i) { + BUG_ON(!sg_page(s)); + + dma_cache_sync(dev, sg_virt(s), s->length, dir); + + s->dma_address = sg_phys(s); + s->dma_length = s->length; + } + + return nents; +} + +#ifdef CONFIG_DMA_NONCOHERENT +static void nommu_sync_single(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir) +{ + dma_cache_sync(dev, phys_to_virt(addr), size, dir); +} + +static void nommu_sync_sg(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction dir) +{ + struct scatterlist *s; + int i; + + for_each_sg(sg, s, nelems, i) + dma_cache_sync(dev, sg_virt(s), s->length, dir); +} +#endif + +struct dma_map_ops nommu_dma_ops = { + .alloc_coherent = dma_generic_alloc_coherent, + .free_coherent = dma_generic_free_coherent, + .map_page = nommu_map_page, + .map_sg = nommu_map_sg, +#ifdef CONFIG_DMA_NONCOHERENT + .sync_single_for_device = nommu_sync_single, + .sync_sg_for_device = nommu_sync_sg, +#endif + .is_phys = 1, +}; + +void __init no_iommu_init(void) +{ + if (dma_ops) + return; + dma_ops = &nommu_dma_ops; +} diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index d76a23170dbb..3576b709f052 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c @@ -20,6 +20,7 @@ #include <linux/list.h> #include <linux/mempool.h> #include <linux/mm.h> +#include <linux/elf.h> #include <linux/ftrace.h> #include <asm/dwarf.h> #include <asm/unwinder.h> @@ -530,7 +531,18 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start, } /** - * dwarf_unwind_stack - recursively unwind the stack + * dwarf_free_frame - free the memory allocated for @frame + * @frame: the frame to free + */ +void dwarf_free_frame(struct dwarf_frame *frame) +{ + dwarf_frame_free_regs(frame); + mempool_free(frame, dwarf_frame_pool); +} + +/** + * dwarf_unwind_stack - unwind the stack + * * @pc: address of the function to unwind * @prev: struct dwarf_frame of the previous stackframe on the callstack * @@ -548,9 +560,9 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, unsigned long addr; /* - * If this is the first invocation of this recursive function we - * need get the contents of a physical register to get the CFA - * in order to begin the virtual unwinding of the stack. + * If we're starting at the top of the stack we need get the + * contents of a physical register to get the CFA in order to + * begin the virtual unwinding of the stack. * * NOTE: the return address is guaranteed to be setup by the * time this function makes its first function call. @@ -593,9 +605,8 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, fde = dwarf_lookup_fde(pc); if (!fde) { /* - * This is our normal exit path - the one that stops the - * recursion. There's two reasons why we might exit - * here, + * This is our normal exit path. There are two reasons + * why we might exit here, * * a) pc has no asscociated DWARF frame info and so * we don't know how to unwind this frame. This is @@ -637,10 +648,10 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, } else { /* - * Again, this is the first invocation of this - * recurisve function. We need to physically - * read the contents of a register in order to - * get the Canonical Frame Address for this + * Again, we're starting from the top of the + * stack. We need to physically read + * the contents of a register in order to get + * the Canonical Frame Address for this * function. */ frame->cfa = dwarf_read_arch_reg(frame->cfa_register); @@ -670,13 +681,12 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, return frame; bail: - dwarf_frame_free_regs(frame); - mempool_free(frame, dwarf_frame_pool); + dwarf_free_frame(frame); return NULL; } static int dwarf_parse_cie(void *entry, void *p, unsigned long len, - unsigned char *end) + unsigned char *end, struct module *mod) { struct dwarf_cie *cie; unsigned long flags; @@ -772,6 +782,8 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len, cie->initial_instructions = p; cie->instructions_end = end; + cie->mod = mod; + /* Add to list */ spin_lock_irqsave(&dwarf_cie_lock, flags); list_add_tail(&cie->link, &dwarf_cie_list); @@ -782,7 +794,7 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len, static int dwarf_parse_fde(void *entry, u32 entry_type, void *start, unsigned long len, - unsigned char *end) + unsigned char *end, struct module *mod) { struct dwarf_fde *fde; struct dwarf_cie *cie; @@ -831,6 +843,8 @@ static int dwarf_parse_fde(void *entry, u32 entry_type, fde->instructions = p; fde->end = end; + fde->mod = mod; + /* Add to list. */ spin_lock_irqsave(&dwarf_fde_lock, flags); list_add_tail(&fde->link, &dwarf_fde_list); @@ -854,10 +868,8 @@ static void dwarf_unwinder_dump(struct task_struct *task, while (1) { frame = dwarf_unwind_stack(return_addr, _frame); - if (_frame) { - dwarf_frame_free_regs(_frame); - mempool_free(_frame, dwarf_frame_pool); - } + if (_frame) + dwarf_free_frame(_frame); _frame = frame; @@ -867,6 +879,9 @@ static void dwarf_unwinder_dump(struct task_struct *task, return_addr = frame->return_addr; ops->address(data, return_addr, 1); } + + if (frame) + dwarf_free_frame(frame); } static struct unwinder dwarf_unwinder = { @@ -896,48 +911,28 @@ static void dwarf_unwinder_cleanup(void) } /** - * dwarf_unwinder_init - initialise the dwarf unwinder + * dwarf_parse_section - parse DWARF section + * @eh_frame_start: start address of the .eh_frame section + * @eh_frame_end: end address of the .eh_frame section + * @mod: the kernel module containing the .eh_frame section * - * Build the data structures describing the .dwarf_frame section to - * make it easier to lookup CIE and FDE entries. Because the - * .eh_frame section is packed as tightly as possible it is not - * easy to lookup the FDE for a given PC, so we build a list of FDE - * and CIE entries that make it easier. + * Parse the information in a .eh_frame section. */ -static int __init dwarf_unwinder_init(void) +static int dwarf_parse_section(char *eh_frame_start, char *eh_frame_end, + struct module *mod) { u32 entry_type; void *p, *entry; int count, err = 0; - unsigned long len; + unsigned long len = 0; unsigned int c_entries, f_entries; unsigned char *end; - INIT_LIST_HEAD(&dwarf_cie_list); - INIT_LIST_HEAD(&dwarf_fde_list); c_entries = 0; f_entries = 0; - entry = &__start_eh_frame; - - dwarf_frame_cachep = kmem_cache_create("dwarf_frames", - sizeof(struct dwarf_frame), 0, - SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); - - dwarf_reg_cachep = kmem_cache_create("dwarf_regs", - sizeof(struct dwarf_reg), 0, - SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); + entry = eh_frame_start; - dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ, - mempool_alloc_slab, - mempool_free_slab, - dwarf_frame_cachep); - - dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ, - mempool_alloc_slab, - mempool_free_slab, - dwarf_reg_cachep); - - while ((char *)entry < __stop_eh_frame) { + while ((char *)entry < eh_frame_end) { p = entry; count = dwarf_entry_len(p, &len); @@ -949,6 +944,7 @@ static int __init dwarf_unwinder_init(void) * entry and move to the next one because 'len' * tells us where our next entry is. */ + err = -EINVAL; goto out; } else p += count; @@ -960,13 +956,14 @@ static int __init dwarf_unwinder_init(void) p += 4; if (entry_type == DW_EH_FRAME_CIE) { - err = dwarf_parse_cie(entry, p, len, end); + err = dwarf_parse_cie(entry, p, len, end, mod); if (err < 0) goto out; else c_entries++; } else { - err = dwarf_parse_fde(entry, entry_type, p, len, end); + err = dwarf_parse_fde(entry, entry_type, p, len, + end, mod); if (err < 0) goto out; else @@ -979,6 +976,129 @@ static int __init dwarf_unwinder_init(void) printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n", c_entries, f_entries); + return 0; + +out: + return err; +} + +#ifdef CONFIG_MODULES +int module_dwarf_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *me) +{ + unsigned int i, err; + unsigned long start, end; + char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + start = end = 0; + + for (i = 1; i < hdr->e_shnum; i++) { + /* Alloc bit cleared means "ignore it." */ + if ((sechdrs[i].sh_flags & SHF_ALLOC) + && !strcmp(secstrings+sechdrs[i].sh_name, ".eh_frame")) { + start = sechdrs[i].sh_addr; + end = start + sechdrs[i].sh_size; + break; + } + } + + /* Did we find the .eh_frame section? */ + if (i != hdr->e_shnum) { + err = dwarf_parse_section((char *)start, (char *)end, me); + if (err) { + printk(KERN_WARNING "%s: failed to parse DWARF info\n", + me->name); + return err; + } + } + + return 0; +} + +/** + * module_dwarf_cleanup - remove FDE/CIEs associated with @mod + * @mod: the module that is being unloaded + * + * Remove any FDEs and CIEs from the global lists that came from + * @mod's .eh_frame section because @mod is being unloaded. + */ +void module_dwarf_cleanup(struct module *mod) +{ + struct dwarf_fde *fde; + struct dwarf_cie *cie; + unsigned long flags; + + spin_lock_irqsave(&dwarf_cie_lock, flags); + +again_cie: + list_for_each_entry(cie, &dwarf_cie_list, link) { + if (cie->mod == mod) + break; + } + + if (&cie->link != &dwarf_cie_list) { + list_del(&cie->link); + kfree(cie); + goto again_cie; + } + + spin_unlock_irqrestore(&dwarf_cie_lock, flags); + + spin_lock_irqsave(&dwarf_fde_lock, flags); + +again_fde: + list_for_each_entry(fde, &dwarf_fde_list, link) { + if (fde->mod == mod) + break; + } + + if (&fde->link != &dwarf_fde_list) { + list_del(&fde->link); + kfree(fde); + goto again_fde; + } + + spin_unlock_irqrestore(&dwarf_fde_lock, flags); +} +#endif /* CONFIG_MODULES */ + +/** + * dwarf_unwinder_init - initialise the dwarf unwinder + * + * Build the data structures describing the .dwarf_frame section to + * make it easier to lookup CIE and FDE entries. Because the + * .eh_frame section is packed as tightly as possible it is not + * easy to lookup the FDE for a given PC, so we build a list of FDE + * and CIE entries that make it easier. + */ +static int __init dwarf_unwinder_init(void) +{ + int err; + INIT_LIST_HEAD(&dwarf_cie_list); + INIT_LIST_HEAD(&dwarf_fde_list); + + dwarf_frame_cachep = kmem_cache_create("dwarf_frames", + sizeof(struct dwarf_frame), 0, + SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); + + dwarf_reg_cachep = kmem_cache_create("dwarf_regs", + sizeof(struct dwarf_reg), 0, + SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); + + dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ, + mempool_alloc_slab, + mempool_free_slab, + dwarf_frame_cachep); + + dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ, + mempool_alloc_slab, + mempool_free_slab, + dwarf_reg_cachep); + + err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL); + if (err) + goto out; + err = unwinder_register(&dwarf_unwinder); if (err) goto out; diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 3eb84931d2aa..f0abd58c3a69 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -133,7 +133,7 @@ work_pending: ! r8: current_thread_info ! t: result of "tst #_TIF_NEED_RESCHED, r0" bf/s work_resched - tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 + tst #_TIF_SIGPENDING, r0 work_notifysig: bt/s __restore_all mov r15, r4 diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 2c48e267256e..b6f41c109beb 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c @@ -62,6 +62,150 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) return ftrace_replaced_code; } +/* + * Modifying code must take extra care. On an SMP machine, if + * the code being modified is also being executed on another CPU + * that CPU will have undefined results and possibly take a GPF. + * We use kstop_machine to stop other CPUS from exectuing code. + * But this does not stop NMIs from happening. We still need + * to protect against that. We separate out the modification of + * the code to take care of this. + * + * Two buffers are added: An IP buffer and a "code" buffer. + * + * 1) Put the instruction pointer into the IP buffer + * and the new code into the "code" buffer. + * 2) Wait for any running NMIs to finish and set a flag that says + * we are modifying code, it is done in an atomic operation. + * 3) Write the code + * 4) clear the flag. + * 5) Wait for any running NMIs to finish. + * + * If an NMI is executed, the first thing it does is to call + * "ftrace_nmi_enter". This will check if the flag is set to write + * and if it is, it will write what is in the IP and "code" buffers. + * + * The trick is, it does not matter if everyone is writing the same + * content to the code location. Also, if a CPU is executing code + * it is OK to write to that code location if the contents being written + * are the same as what exists. + */ +#define MOD_CODE_WRITE_FLAG (1 << 31) /* set when NMI should do the write */ +static atomic_t nmi_running = ATOMIC_INIT(0); +static int mod_code_status; /* holds return value of text write */ +static void *mod_code_ip; /* holds the IP to write to */ +static void *mod_code_newcode; /* holds the text to write to the IP */ + +static unsigned nmi_wait_count; +static atomic_t nmi_update_count = ATOMIC_INIT(0); + +int ftrace_arch_read_dyn_info(char *buf, int size) +{ + int r; + + r = snprintf(buf, size, "%u %u", + nmi_wait_count, + atomic_read(&nmi_update_count)); + return r; +} + +static void clear_mod_flag(void) +{ + int old = atomic_read(&nmi_running); + + for (;;) { + int new = old & ~MOD_CODE_WRITE_FLAG; + + if (old == new) + break; + + old = atomic_cmpxchg(&nmi_running, old, new); + } +} + +static void ftrace_mod_code(void) +{ + /* + * Yes, more than one CPU process can be writing to mod_code_status. + * (and the code itself) + * But if one were to fail, then they all should, and if one were + * to succeed, then they all should. + */ + mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode, + MCOUNT_INSN_SIZE); + + /* if we fail, then kill any new writers */ + if (mod_code_status) + clear_mod_flag(); +} + +void ftrace_nmi_enter(void) +{ + if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) { + smp_rmb(); + ftrace_mod_code(); + atomic_inc(&nmi_update_count); + } + /* Must have previous changes seen before executions */ + smp_mb(); +} + +void ftrace_nmi_exit(void) +{ + /* Finish all executions before clearing nmi_running */ + smp_mb(); + atomic_dec(&nmi_running); +} + +static void wait_for_nmi_and_set_mod_flag(void) +{ + if (!atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)) + return; + + do { + cpu_relax(); + } while (atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)); + + nmi_wait_count++; +} + +static void wait_for_nmi(void) +{ + if (!atomic_read(&nmi_running)) + return; + + do { + cpu_relax(); + } while (atomic_read(&nmi_running)); + + nmi_wait_count++; +} + +static int +do_ftrace_mod_code(unsigned long ip, void *new_code) +{ + mod_code_ip = (void *)ip; + mod_code_newcode = new_code; + + /* The buffers need to be visible before we let NMIs write them */ + smp_mb(); + + wait_for_nmi_and_set_mod_flag(); + + /* Make sure all running NMIs have finished before we write the code */ + smp_mb(); + + ftrace_mod_code(); + + /* Make sure the write happens before clearing the bit */ + smp_mb(); + + clear_mod_flag(); + wait_for_nmi(); + + return mod_code_status; +} + static int ftrace_modify_code(unsigned long ip, unsigned char *old_code, unsigned char *new_code) { @@ -86,7 +230,7 @@ static int ftrace_modify_code(unsigned long ip, unsigned char *old_code, return -EINVAL; /* replace the text with the new text */ - if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) + if (do_ftrace_mod_code(ip, new_code)) return -EPERM; flush_icache_range(ip, ip + MCOUNT_INSN_SIZE); diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c deleted file mode 100644 index d22e5af699f9..000000000000 --- a/arch/sh/kernel/gpio.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Pinmuxed GPIO support for SuperH. - * - * Copyright (C) 2008 Magnus Damm - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/bitops.h> -#include <linux/gpio.h> - -static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) -{ - if (enum_id < r->begin) - return 0; - - if (enum_id > r->end) - return 0; - - return 1; -} - -static unsigned long gpio_read_raw_reg(unsigned long reg, - unsigned long reg_width) -{ - switch (reg_width) { - case 8: - return ctrl_inb(reg); - case 16: - return ctrl_inw(reg); - case 32: - return ctrl_inl(reg); - } - - BUG(); - return 0; -} - -static void gpio_write_raw_reg(unsigned long reg, - unsigned long reg_width, - unsigned long data) -{ - switch (reg_width) { - case 8: - ctrl_outb(data, reg); - return; - case 16: - ctrl_outw(data, reg); - return; - case 32: - ctrl_outl(data, reg); - return; - } - - BUG(); -} - -static void gpio_write_bit(struct pinmux_data_reg *dr, - unsigned long in_pos, unsigned long value) -{ - unsigned long pos; - - pos = dr->reg_width - (in_pos + 1); - -#ifdef DEBUG - pr_info("write_bit addr = %lx, value = %ld, pos = %ld, " - "r_width = %ld\n", - dr->reg, !!value, pos, dr->reg_width); -#endif - - if (value) - set_bit(pos, &dr->reg_shadow); - else - clear_bit(pos, &dr->reg_shadow); - - gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow); -} - -static int gpio_read_reg(unsigned long reg, unsigned long reg_width, - unsigned long field_width, unsigned long in_pos) -{ - unsigned long data, mask, pos; - - data = 0; - mask = (1 << field_width) - 1; - pos = reg_width - ((in_pos + 1) * field_width); - -#ifdef DEBUG - pr_info("read_reg: addr = %lx, pos = %ld, " - "r_width = %ld, f_width = %ld\n", - reg, pos, reg_width, field_width); -#endif - - data = gpio_read_raw_reg(reg, reg_width); - return (data >> pos) & mask; -} - -static void gpio_write_reg(unsigned long reg, unsigned long reg_width, - unsigned long field_width, unsigned long in_pos, - unsigned long value) -{ - unsigned long mask, pos; - - mask = (1 << field_width) - 1; - pos = reg_width - ((in_pos + 1) * field_width); - -#ifdef DEBUG - pr_info("write_reg addr = %lx, value = %ld, pos = %ld, " - "r_width = %ld, f_width = %ld\n", - reg, value, pos, reg_width, field_width); -#endif - - mask = ~(mask << pos); - value = value << pos; - - switch (reg_width) { - case 8: - ctrl_outb((ctrl_inb(reg) & mask) | value, reg); - break; - case 16: - ctrl_outw((ctrl_inw(reg) & mask) | value, reg); - break; - case 32: - ctrl_outl((ctrl_inl(reg) & mask) | value, reg); - break; - } -} - -static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) -{ - struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; - struct pinmux_data_reg *data_reg; - int k, n; - - if (!enum_in_range(gpiop->enum_id, &gpioc->data)) - return -1; - - k = 0; - while (1) { - data_reg = gpioc->data_regs + k; - - if (!data_reg->reg_width) - break; - - for (n = 0; n < data_reg->reg_width; n++) { - if (data_reg->enum_ids[n] == gpiop->enum_id) { - gpiop->flags &= ~PINMUX_FLAG_DREG; - gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT); - gpiop->flags &= ~PINMUX_FLAG_DBIT; - gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT); - return 0; - } - } - k++; - } - - BUG(); - - return -1; -} - -static void setup_data_regs(struct pinmux_info *gpioc) -{ - struct pinmux_data_reg *drp; - int k; - - for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++) - setup_data_reg(gpioc, k); - - k = 0; - while (1) { - drp = gpioc->data_regs + k; - - if (!drp->reg_width) - break; - - drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width); - k++; - } -} - -static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, - struct pinmux_data_reg **drp, int *bitp) -{ - struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; - int k, n; - - if (!enum_in_range(gpiop->enum_id, &gpioc->data)) - return -1; - - k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; - n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; - *drp = gpioc->data_regs + k; - *bitp = n; - return 0; -} - -static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, - struct pinmux_cfg_reg **crp, int *indexp, - unsigned long **cntp) -{ - struct pinmux_cfg_reg *config_reg; - unsigned long r_width, f_width; - int k, n; - - k = 0; - while (1) { - config_reg = gpioc->cfg_regs + k; - - r_width = config_reg->reg_width; - f_width = config_reg->field_width; - - if (!r_width) - break; - for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) { - if (config_reg->enum_ids[n] == enum_id) { - *crp = config_reg; - *indexp = n; - *cntp = &config_reg->cnt[n / (1 << f_width)]; - return 0; - } - } - k++; - } - - return -1; -} - -static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, - int pos, pinmux_enum_t *enum_idp) -{ - pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; - pinmux_enum_t *data = gpioc->gpio_data; - int k; - - if (!enum_in_range(enum_id, &gpioc->data)) { - if (!enum_in_range(enum_id, &gpioc->mark)) { - pr_err("non data/mark enum_id for gpio %d\n", gpio); - return -1; - } - } - - if (pos) { - *enum_idp = data[pos + 1]; - return pos + 1; - } - - for (k = 0; k < gpioc->gpio_data_size; k++) { - if (data[k] == enum_id) { - *enum_idp = data[k + 1]; - return k + 1; - } - } - - pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); - return -1; -} - -static void write_config_reg(struct pinmux_info *gpioc, - struct pinmux_cfg_reg *crp, - int index) -{ - unsigned long ncomb, pos, value; - - ncomb = 1 << crp->field_width; - pos = index / ncomb; - value = index % ncomb; - - gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value); -} - -static int check_config_reg(struct pinmux_info *gpioc, - struct pinmux_cfg_reg *crp, - int index) -{ - unsigned long ncomb, pos, value; - - ncomb = 1 << crp->field_width; - pos = index / ncomb; - value = index % ncomb; - - if (gpio_read_reg(crp->reg, crp->reg_width, - crp->field_width, pos) == value) - return 0; - - return -1; -} - -enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; - -static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, - int pinmux_type, int cfg_mode) -{ - struct pinmux_cfg_reg *cr = NULL; - pinmux_enum_t enum_id; - struct pinmux_range *range; - int in_range, pos, index; - unsigned long *cntp; - - switch (pinmux_type) { - - case PINMUX_TYPE_FUNCTION: - range = NULL; - break; - - case PINMUX_TYPE_OUTPUT: - range = &gpioc->output; - break; - - case PINMUX_TYPE_INPUT: - range = &gpioc->input; - break; - - case PINMUX_TYPE_INPUT_PULLUP: - range = &gpioc->input_pu; - break; - - case PINMUX_TYPE_INPUT_PULLDOWN: - range = &gpioc->input_pd; - break; - - default: - goto out_err; - } - - pos = 0; - enum_id = 0; - index = 0; - while (1) { - pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id); - if (pos <= 0) - goto out_err; - - if (!enum_id) - break; - - in_range = enum_in_range(enum_id, &gpioc->function); - if (!in_range && range) { - in_range = enum_in_range(enum_id, range); - - if (in_range && enum_id == range->force) - continue; - } - - if (!in_range) - continue; - - if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0) - goto out_err; - - switch (cfg_mode) { - case GPIO_CFG_DRYRUN: - if (!*cntp || !check_config_reg(gpioc, cr, index)) - continue; - break; - - case GPIO_CFG_REQ: - write_config_reg(gpioc, cr, index); - *cntp = *cntp + 1; - break; - - case GPIO_CFG_FREE: - *cntp = *cntp - 1; - break; - } - } - - return 0; - out_err: - return -1; -} - -static DEFINE_SPINLOCK(gpio_lock); - -static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip) -{ - return container_of(chip, struct pinmux_info, chip); -} - -static int sh_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct pinmux_info *gpioc = chip_to_pinmux(chip); - struct pinmux_data_reg *dummy; - unsigned long flags; - int i, ret, pinmux_type; - - ret = -EINVAL; - - if (!gpioc) - goto err_out; - - spin_lock_irqsave(&gpio_lock, flags); - - if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) - goto err_unlock; - - /* setup pin function here if no data is associated with pin */ - - if (get_data_reg(gpioc, offset, &dummy, &i) != 0) - pinmux_type = PINMUX_TYPE_FUNCTION; - else - pinmux_type = PINMUX_TYPE_GPIO; - - if (pinmux_type == PINMUX_TYPE_FUNCTION) { - if (pinmux_config_gpio(gpioc, offset, - pinmux_type, - GPIO_CFG_DRYRUN) != 0) - goto err_unlock; - - if (pinmux_config_gpio(gpioc, offset, - pinmux_type, - GPIO_CFG_REQ) != 0) - BUG(); - } - - gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; - gpioc->gpios[offset].flags |= pinmux_type; - - ret = 0; - err_unlock: - spin_unlock_irqrestore(&gpio_lock, flags); - err_out: - return ret; -} - -static void sh_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct pinmux_info *gpioc = chip_to_pinmux(chip); - unsigned long flags; - int pinmux_type; - - if (!gpioc) - return; - - spin_lock_irqsave(&gpio_lock, flags); - - pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE; - pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE); - gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; - gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE; - - spin_unlock_irqrestore(&gpio_lock, flags); -} - -static int pinmux_direction(struct pinmux_info *gpioc, - unsigned gpio, int new_pinmux_type) -{ - int pinmux_type; - int ret = -EINVAL; - - if (!gpioc) - goto err_out; - - pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; - - switch (pinmux_type) { - case PINMUX_TYPE_GPIO: - break; - case PINMUX_TYPE_OUTPUT: - case PINMUX_TYPE_INPUT: - case PINMUX_TYPE_INPUT_PULLUP: - case PINMUX_TYPE_INPUT_PULLDOWN: - pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); - break; - default: - goto err_out; - } - - if (pinmux_config_gpio(gpioc, gpio, - new_pinmux_type, - GPIO_CFG_DRYRUN) != 0) - goto err_out; - - if (pinmux_config_gpio(gpioc, gpio, - new_pinmux_type, - GPIO_CFG_REQ) != 0) - BUG(); - - gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; - gpioc->gpios[gpio].flags |= new_pinmux_type; - - ret = 0; - err_out: - return ret; -} - -static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct pinmux_info *gpioc = chip_to_pinmux(chip); - unsigned long flags; - int ret; - - spin_lock_irqsave(&gpio_lock, flags); - ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT); - spin_unlock_irqrestore(&gpio_lock, flags); - - return ret; -} - -static void sh_gpio_set_value(struct pinmux_info *gpioc, - unsigned gpio, int value) -{ - struct pinmux_data_reg *dr = NULL; - int bit = 0; - - if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) - BUG(); - else - gpio_write_bit(dr, bit, value); -} - -static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct pinmux_info *gpioc = chip_to_pinmux(chip); - unsigned long flags; - int ret; - - sh_gpio_set_value(gpioc, offset, value); - spin_lock_irqsave(&gpio_lock, flags); - ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT); - spin_unlock_irqrestore(&gpio_lock, flags); - - return ret; -} - -static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) -{ - struct pinmux_data_reg *dr = NULL; - int bit = 0; - - if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) { - BUG(); - return 0; - } - - return gpio_read_reg(dr->reg, dr->reg_width, 1, bit); -} - -static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return sh_gpio_get_value(chip_to_pinmux(chip), offset); -} - -static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - sh_gpio_set_value(chip_to_pinmux(chip), offset, value); -} - -int register_pinmux(struct pinmux_info *pip) -{ - struct gpio_chip *chip = &pip->chip; - - pr_info("sh pinmux: %s handling gpio %d -> %d\n", - pip->name, pip->first_gpio, pip->last_gpio); - - setup_data_regs(pip); - - chip->request = sh_gpio_request; - chip->free = sh_gpio_free; - chip->direction_input = sh_gpio_direction_input; - chip->get = sh_gpio_get; - chip->direction_output = sh_gpio_direction_output; - chip->set = sh_gpio_set; - - WARN_ON(pip->first_gpio != 0); /* needs testing */ - - chip->label = pip->name; - chip->owner = THIS_MODULE; - chip->base = pip->first_gpio; - chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; - - return gpiochip_add(chip); -} diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index a78be74b8d3e..1151ecdffa71 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S @@ -33,7 +33,7 @@ ENTRY(empty_zero_page) .long 1 /* LOADER_TYPE */ .long 0x00000000 /* INITRD_START */ .long 0x00000000 /* INITRD_SIZE */ -#ifdef CONFIG_32BIT +#if defined(CONFIG_32BIT) && defined(CONFIG_PMB_FIXED) .long 0x53453f00 + 32 /* "SE?" = 32 bit */ #else .long 0x53453f00 + 29 /* "SE?" = 29 bit */ diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 27ff2dc093c7..aaff0037fcd7 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -21,7 +21,7 @@ #include <asm/atomic.h> static int hlt_counter; -void (*pm_idle)(void); +void (*pm_idle)(void) = NULL; void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); @@ -39,48 +39,92 @@ static int __init hlt_setup(char *__unused) } __setup("hlt", hlt_setup); +static inline int hlt_works(void) +{ + return !hlt_counter; +} + +/* + * On SMP it's slightly faster (but much more power-consuming!) + * to poll the ->work.need_resched flag instead of waiting for the + * cross-CPU IPI to arrive. Use this option with caution. + */ +static void poll_idle(void) +{ + local_irq_enable(); + while (!need_resched()) + cpu_relax(); +} + void default_idle(void) { - if (!hlt_counter) { + if (hlt_works()) { clear_thread_flag(TIF_POLLING_NRFLAG); smp_mb__after_clear_bit(); - set_bl_bit(); - stop_critical_timings(); - while (!need_resched()) + if (!need_resched()) { + local_irq_enable(); cpu_sleep(); + } else + local_irq_enable(); - start_critical_timings(); - clear_bl_bit(); set_thread_flag(TIF_POLLING_NRFLAG); } else - while (!need_resched()) - cpu_relax(); + poll_idle(); } +/* + * The idle thread. There's no useful work to be done, so just try to conserve + * power and have a low exit latency (ie sit in a loop waiting for somebody to + * say that they'd like to reschedule) + */ void cpu_idle(void) { + unsigned int cpu = smp_processor_id(); + set_thread_flag(TIF_POLLING_NRFLAG); /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; + tick_nohz_stop_sched_tick(1); - if (!idle) - idle = default_idle; + while (!need_resched() && cpu_online(cpu)) { + check_pgt_cache(); + rmb(); - tick_nohz_stop_sched_tick(1); - while (!need_resched()) - idle(); - tick_nohz_restart_sched_tick(); + local_irq_disable(); + /* Don't trace irqs off for idle */ + stop_critical_timings(); + pm_idle(); + /* + * Sanity check to ensure that pm_idle() returns + * with IRQs enabled + */ + WARN_ON(irqs_disabled()); + start_critical_timings(); + } + tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); preempt_disable(); - check_pgt_cache(); } } +void __cpuinit select_idle_routine(void) +{ + /* + * If a platform has set its own idle routine, leave it alone. + */ + if (pm_idle) + return; + + if (hlt_works()) + pm_idle = default_idle; + else + pm_idle = poll_idle; +} + static void do_nothing(void *unused) { } diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index b8fa6524760a..e1e1dbd19557 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -24,7 +24,7 @@ #define dummy_read() #endif -unsigned long generic_io_base; +unsigned long generic_io_base = 0; u8 generic_inb(unsigned long port) { @@ -147,8 +147,10 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count) void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) { +#ifdef P1SEG if (PXSEG(addr) >= P1SEG) return (void __iomem *)addr; +#endif return (void __iomem *)(addr + generic_io_base); } diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index eac7da772fc2..e1913f28f418 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -37,7 +37,15 @@ void ack_bad_irq(unsigned int irq) */ static int show_other_interrupts(struct seq_file *p, int prec) { + int j; + + seq_printf(p, "%*s: ", prec, "NMI"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stat[j].__nmi_count); + seq_printf(p, " Non-maskable interrupts\n"); + seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); + return 0; } @@ -255,6 +263,12 @@ void __init init_IRQ(void) { plat_irq_setup(); + /* + * Pin any of the legacy IRQ vectors that haven't already been + * grabbed by the platform + */ + reserve_irq_legacy(); + /* Perform the machine specific initialisation */ if (sh_mv.mv_init_irq) sh_mv.mv_init_irq(); diff --git a/arch/sh/kernel/irq_32.c b/arch/sh/kernel/irq_32.c new file mode 100644 index 000000000000..e33ab15831f9 --- /dev/null +++ b/arch/sh/kernel/irq_32.c @@ -0,0 +1,57 @@ +/* + * SHcompact irqflags support + * + * Copyright (C) 2006 - 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/irqflags.h> +#include <linux/module.h> + +void notrace raw_local_irq_restore(unsigned long flags) +{ + unsigned long __dummy0, __dummy1; + + if (flags == RAW_IRQ_DISABLED) { + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "or #0xf0, %0\n\t" + "ldc %0, sr\n\t" + : "=&z" (__dummy0) + : /* no inputs */ + : "memory" + ); + } else { + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and %1, %0\n\t" +#ifdef CONFIG_CPU_HAS_SR_RB + "stc r6_bank, %1\n\t" + "or %1, %0\n\t" +#endif + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "1" (~RAW_IRQ_DISABLED) + : "memory" + ); + } +} +EXPORT_SYMBOL(raw_local_irq_restore); + +unsigned long notrace __raw_local_save_flags(void) +{ + unsigned long flags; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and #0xf0, %0\n\t" + : "=&z" (flags) + : /* no inputs */ + : "memory" + ); + + return flags; +} +EXPORT_SYMBOL(__raw_local_save_flags); diff --git a/arch/sh/kernel/irq_64.c b/arch/sh/kernel/irq_64.c new file mode 100644 index 000000000000..32365ba0e039 --- /dev/null +++ b/arch/sh/kernel/irq_64.c @@ -0,0 +1,51 @@ +/* + * SHmedia irqflags support + * + * Copyright (C) 2006 - 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/irqflags.h> +#include <linux/module.h> +#include <cpu/registers.h> + +void notrace raw_local_irq_restore(unsigned long flags) +{ + unsigned long long __dummy; + + if (flags == RAW_IRQ_DISABLED) { + __asm__ __volatile__ ( + "getcon " __SR ", %0\n\t" + "or %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy) + : "r" (RAW_IRQ_DISABLED) + ); + } else { + __asm__ __volatile__ ( + "getcon " __SR ", %0\n\t" + "and %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy) + : "r" (~RAW_IRQ_DISABLED) + ); + } +} +EXPORT_SYMBOL(raw_local_irq_restore); + +unsigned long notrace __raw_local_save_flags(void) +{ + unsigned long flags; + + __asm__ __volatile__ ( + "getcon " __SR ", %0\n\t" + "and %0, %1, %0" + : "=&r" (flags) + : "r" (RAW_IRQ_DISABLED) + ); + + return flags; +} +EXPORT_SYMBOL(__raw_local_save_flags); diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 7ea2704ea033..76f280223ebd 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -46,12 +46,6 @@ void machine_crash_shutdown(struct pt_regs *regs) */ int machine_kexec_prepare(struct kimage *image) { - /* older versions of kexec-tools are passing - * the zImage entry point as a virtual address. - */ - if (image->start != PHYSADDR(image->start)) - return -EINVAL; /* upgrade your kexec-tools */ - return 0; } diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c index cbce639b108a..1652340ba3f2 100644 --- a/arch/sh/kernel/machvec.c +++ b/arch/sh/kernel/machvec.c @@ -135,5 +135,9 @@ void __init sh_mv_setup(void) if (!sh_mv.mv_nr_irqs) sh_mv.mv_nr_irqs = NR_IRQS; +#ifdef P2SEG __set_io_port_base(P2SEG); +#else + __set_io_port_base(0); +#endif } diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index c2efdcde266f..43adddfe4c04 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -32,6 +32,7 @@ #include <linux/string.h> #include <linux/kernel.h> #include <asm/unaligned.h> +#include <asm/dwarf.h> void *module_alloc(unsigned long size) { @@ -145,10 +146,16 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - return module_bug_finalize(hdr, sechdrs, me); + int ret = 0; + + ret |= module_dwarf_finalize(hdr, sechdrs, me); + ret |= module_bug_finalize(hdr, sechdrs, me); + + return ret; } void module_arch_cleanup(struct module *mod) { module_bug_cleanup(mod); + module_dwarf_cleanup(mod); } diff --git a/arch/sh/kernel/perf_callchain.c b/arch/sh/kernel/perf_callchain.c new file mode 100644 index 000000000000..24ea837eac5b --- /dev/null +++ b/arch/sh/kernel/perf_callchain.c @@ -0,0 +1,98 @@ +/* + * Performance event callchain support - SuperH architecture code + * + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/perf_event.h> +#include <linux/percpu.h> +#include <asm/unwinder.h> +#include <asm/ptrace.h> + +static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) +{ + if (entry->nr < PERF_MAX_STACK_DEPTH) + entry->ip[entry->nr++] = ip; +} + +static void callchain_warning(void *data, char *msg) +{ +} + +static void +callchain_warning_symbol(void *data, char *msg, unsigned long symbol) +{ +} + +static int callchain_stack(void *data, char *name) +{ + return 0; +} + +static void callchain_address(void *data, unsigned long addr, int reliable) +{ + struct perf_callchain_entry *entry = data; + + if (reliable) + callchain_store(entry, addr); +} + +static const struct stacktrace_ops callchain_ops = { + .warning = callchain_warning, + .warning_symbol = callchain_warning_symbol, + .stack = callchain_stack, + .address = callchain_address, +}; + +static void +perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) +{ + callchain_store(entry, PERF_CONTEXT_KERNEL); + callchain_store(entry, regs->pc); + + unwind_stack(NULL, regs, NULL, &callchain_ops, entry); +} + +static void +perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry) +{ + int is_user; + + if (!regs) + return; + + is_user = user_mode(regs); + + if (!current || current->pid == 0) + return; + + if (is_user && current->state != TASK_RUNNING) + return; + + /* + * Only the kernel side is implemented for now. + */ + if (!is_user) + perf_callchain_kernel(regs, entry); +} + +/* + * No need for separate IRQ and NMI entries. + */ +static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); + +struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) +{ + struct perf_callchain_entry *entry = &__get_cpu_var(callchain); + + entry->nr = 0; + + perf_do_callchain(regs, entry); + + return entry; +} diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c new file mode 100644 index 000000000000..7ff0943e7a08 --- /dev/null +++ b/arch/sh/kernel/perf_event.c @@ -0,0 +1,312 @@ +/* + * Performance event support framework for SuperH hardware counters. + * + * Copyright (C) 2009 Paul Mundt + * + * Heavily based on the x86 and PowerPC implementations. + * + * x86: + * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> + * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar + * Copyright (C) 2009 Jaswinder Singh Rajput + * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter + * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> + * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> + * + * ppc: + * Copyright 2008-2009 Paul Mackerras, IBM Corporation. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/perf_event.h> +#include <asm/processor.h> + +struct cpu_hw_events { + struct perf_event *events[MAX_HWEVENTS]; + unsigned long used_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; + unsigned long active_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; +}; + +DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); + +static struct sh_pmu *sh_pmu __read_mostly; + +/* Number of perf_events counting hardware events */ +static atomic_t num_events; +/* Used to avoid races in calling reserve/release_pmc_hardware */ +static DEFINE_MUTEX(pmc_reserve_mutex); + +/* + * Stub these out for now, do something more profound later. + */ +int reserve_pmc_hardware(void) +{ + return 0; +} + +void release_pmc_hardware(void) +{ +} + +static inline int sh_pmu_initialized(void) +{ + return !!sh_pmu; +} + +/* + * Release the PMU if this is the last perf_event. + */ +static void hw_perf_event_destroy(struct perf_event *event) +{ + if (!atomic_add_unless(&num_events, -1, 1)) { + mutex_lock(&pmc_reserve_mutex); + if (atomic_dec_return(&num_events) == 0) + release_pmc_hardware(); + mutex_unlock(&pmc_reserve_mutex); + } +} + +static int hw_perf_cache_event(int config, int *evp) +{ + unsigned long type, op, result; + int ev; + + if (!sh_pmu->cache_events) + return -EINVAL; + + /* unpack config */ + type = config & 0xff; + op = (config >> 8) & 0xff; + result = (config >> 16) & 0xff; + + if (type >= PERF_COUNT_HW_CACHE_MAX || + op >= PERF_COUNT_HW_CACHE_OP_MAX || + result >= PERF_COUNT_HW_CACHE_RESULT_MAX) + return -EINVAL; + + ev = (*sh_pmu->cache_events)[type][op][result]; + if (ev == 0) + return -EOPNOTSUPP; + if (ev == -1) + return -EINVAL; + *evp = ev; + return 0; +} + +static int __hw_perf_event_init(struct perf_event *event) +{ + struct perf_event_attr *attr = &event->attr; + struct hw_perf_event *hwc = &event->hw; + int config = -1; + int err; + + if (!sh_pmu_initialized()) + return -ENODEV; + + /* + * All of the on-chip counters are "limited", in that they have + * no interrupts, and are therefore unable to do sampling without + * further work and timer assistance. + */ + if (hwc->sample_period) + return -EINVAL; + + /* + * See if we need to reserve the counter. + * + * If no events are currently in use, then we have to take a + * mutex to ensure that we don't race with another task doing + * reserve_pmc_hardware or release_pmc_hardware. + */ + err = 0; + if (!atomic_inc_not_zero(&num_events)) { + mutex_lock(&pmc_reserve_mutex); + if (atomic_read(&num_events) == 0 && + reserve_pmc_hardware()) + err = -EBUSY; + else + atomic_inc(&num_events); + mutex_unlock(&pmc_reserve_mutex); + } + + if (err) + return err; + + event->destroy = hw_perf_event_destroy; + + switch (attr->type) { + case PERF_TYPE_RAW: + config = attr->config & sh_pmu->raw_event_mask; + break; + case PERF_TYPE_HW_CACHE: + err = hw_perf_cache_event(attr->config, &config); + if (err) + return err; + break; + case PERF_TYPE_HARDWARE: + if (attr->config >= sh_pmu->max_events) + return -EINVAL; + + config = sh_pmu->event_map(attr->config); + break; + } + + if (config == -1) + return -EINVAL; + + hwc->config |= config; + + return 0; +} + +static void sh_perf_event_update(struct perf_event *event, + struct hw_perf_event *hwc, int idx) +{ + u64 prev_raw_count, new_raw_count; + s64 delta; + int shift = 0; + + /* + * Depending on the counter configuration, they may or may not + * be chained, in which case the previous counter value can be + * updated underneath us if the lower-half overflows. + * + * Our tactic to handle this is to first atomically read and + * exchange a new raw count - then add that new-prev delta + * count to the generic counter atomically. + * + * As there is no interrupt associated with the overflow events, + * this is the simplest approach for maintaining consistency. + */ +again: + prev_raw_count = atomic64_read(&hwc->prev_count); + new_raw_count = sh_pmu->read(idx); + + if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count, + new_raw_count) != prev_raw_count) + goto again; + + /* + * Now we have the new raw value and have updated the prev + * timestamp already. We can now calculate the elapsed delta + * (counter-)time and add that to the generic counter. + * + * Careful, not all hw sign-extends above the physical width + * of the count. + */ + delta = (new_raw_count << shift) - (prev_raw_count << shift); + delta >>= shift; + + atomic64_add(delta, &event->count); +} + +static void sh_pmu_disable(struct perf_event *event) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + clear_bit(idx, cpuc->active_mask); + sh_pmu->disable(hwc, idx); + + barrier(); + + sh_perf_event_update(event, &event->hw, idx); + + cpuc->events[idx] = NULL; + clear_bit(idx, cpuc->used_mask); + + perf_event_update_userpage(event); +} + +static int sh_pmu_enable(struct perf_event *event) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + if (test_and_set_bit(idx, cpuc->used_mask)) { + idx = find_first_zero_bit(cpuc->used_mask, sh_pmu->num_events); + if (idx == sh_pmu->num_events) + return -EAGAIN; + + set_bit(idx, cpuc->used_mask); + hwc->idx = idx; + } + + sh_pmu->disable(hwc, idx); + + cpuc->events[idx] = event; + set_bit(idx, cpuc->active_mask); + + sh_pmu->enable(hwc, idx); + + perf_event_update_userpage(event); + + return 0; +} + +static void sh_pmu_read(struct perf_event *event) +{ + sh_perf_event_update(event, &event->hw, event->hw.idx); +} + +static const struct pmu pmu = { + .enable = sh_pmu_enable, + .disable = sh_pmu_disable, + .read = sh_pmu_read, +}; + +const struct pmu *hw_perf_event_init(struct perf_event *event) +{ + int err = __hw_perf_event_init(event); + if (unlikely(err)) { + if (event->destroy) + event->destroy(event); + return ERR_PTR(err); + } + + return &pmu; +} + +void hw_perf_event_setup(int cpu) +{ + struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); + + memset(cpuhw, 0, sizeof(struct cpu_hw_events)); +} + +void hw_perf_enable(void) +{ + if (!sh_pmu_initialized()) + return; + + sh_pmu->enable_all(); +} + +void hw_perf_disable(void) +{ + if (!sh_pmu_initialized()) + return; + + sh_pmu->disable_all(); +} + +int register_sh_pmu(struct sh_pmu *pmu) +{ + if (sh_pmu) + return -EBUSY; + sh_pmu = pmu; + + pr_info("Performance Events: %s support registered\n", pmu->name); + + WARN_ON(pmu->num_events > MAX_HWEVENTS); + + return 0; +} diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 0673c4746be3..d8af889366a4 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -134,7 +134,10 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) regs.regs[5] = (unsigned long)fn; regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = (1 << 30); + regs.sr = SR_MD; +#if defined(CONFIG_SH_FPU) + regs.sr |= SR_FD; +#endif /* Ok, create the new process.. */ pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, @@ -142,6 +145,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) return pid; } +EXPORT_SYMBOL(kernel_thread); /* * Free current thread data structures etc.. @@ -186,6 +190,16 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) return fpvalid; } +EXPORT_SYMBOL(dump_fpu); + +/* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + unlazy_fpu(tsk, task_pt_regs(tsk)); +} asmlinkage void ret_from_fork(void); @@ -195,16 +209,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; -#if defined(CONFIG_SH_FPU) || defined(CONFIG_SH_DSP) +#if defined(CONFIG_SH_DSP) struct task_struct *tsk = current; #endif -#if defined(CONFIG_SH_FPU) - unlazy_fpu(tsk, regs); - p->thread.fpu = tsk->thread.fpu; - copy_to_stopped_child_used_math(p); -#endif - #if defined(CONFIG_SH_DSP) if (is_dsp_enabled(tsk)) { /* We can use the __save_dsp or just copy the struct: @@ -224,6 +232,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, } else { childregs->regs[15] = (unsigned long)childregs; ti->addr_limit = KERNEL_DS; + ti->status &= ~TS_USEDFPU; + p->fpu_counter = 0; } if (clone_flags & CLONE_SETTLS) @@ -288,9 +298,13 @@ static void ubc_set_tracing(int asid, unsigned long pc) __notrace_funcgraph struct task_struct * __switch_to(struct task_struct *prev, struct task_struct *next) { -#if defined(CONFIG_SH_FPU) + struct thread_struct *next_t = &next->thread; + unlazy_fpu(prev, task_pt_regs(prev)); -#endif + + /* we're going to use this soon, after a few expensive things */ + if (next->fpu_counter > 5) + prefetch(&next_t->fpu.hard); #ifdef CONFIG_MMU /* @@ -321,6 +335,14 @@ __switch_to(struct task_struct *prev, struct task_struct *next) #endif } + /* + * If the task has used fpu the last 5 timeslices, just do a full + * restore of the math state immediately to avoid the trap; the + * chances of needing FPU soon are obviously high now + */ + if (next->fpu_counter > 5) + fpu_state_restore(task_pt_regs(next)); + return prev; } diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 1192398ef582..359b8a2f4d2e 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -335,6 +335,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } +EXPORT_SYMBOL(kernel_thread); /* * Free current thread data structures etc.. @@ -417,6 +418,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) return 0; /* Task didn't use the fpu at all. */ #endif } +EXPORT_SYMBOL(dump_fpu); asmlinkage void ret_from_fork(void); diff --git a/arch/sh/kernel/return_address.c b/arch/sh/kernel/return_address.c new file mode 100644 index 000000000000..df3ab5811074 --- /dev/null +++ b/arch/sh/kernel/return_address.c @@ -0,0 +1,54 @@ +/* + * arch/sh/kernel/return_address.c + * + * Copyright (C) 2009 Matt Fleming + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/kernel.h> +#include <asm/dwarf.h> + +#ifdef CONFIG_DWARF_UNWINDER + +void *return_address(unsigned int depth) +{ + struct dwarf_frame *frame; + unsigned long ra; + int i; + + for (i = 0, frame = NULL, ra = 0; i <= depth; i++) { + struct dwarf_frame *tmp; + + tmp = dwarf_unwind_stack(ra, frame); + + if (frame) + dwarf_free_frame(frame); + + frame = tmp; + + if (!frame || !frame->return_addr) + break; + + ra = frame->return_addr; + } + + /* Failed to unwind the stack to the specified depth. */ + WARN_ON(i != depth + 1); + + if (frame) + dwarf_free_frame(frame); + + return (void *)ra; +} + +#else + +void *return_address(unsigned int depth) +{ + return NULL; +} + +#endif diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 99b4fb553bf1..5a947a2567e4 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -453,6 +453,10 @@ void __init setup_arch(char **cmdline_p) paging_init(); +#ifdef CONFIG_PMB_ENABLE + pmb_init(); +#endif + #ifdef CONFIG_SMP plat_smp_setup(); #endif diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 444cce3ae921..3896f26efa4a 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -1,37 +1,11 @@ #include <linux/module.h> -#include <linux/smp.h> -#include <linux/user.h> -#include <linux/elfcore.h> -#include <linux/sched.h> -#include <linux/in6.h> -#include <linux/interrupt.h> -#include <linux/vmalloc.h> -#include <linux/pci.h> -#include <linux/irq.h> -#include <asm/sections.h> -#include <asm/processor.h> -#include <asm/uaccess.h> +#include <linux/string.h> +#include <linux/uaccess.h> +#include <linux/delay.h> +#include <linux/mm.h> #include <asm/checksum.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/tlbflush.h> -#include <asm/cacheflush.h> -#include <asm/ftrace.h> - -extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); - -/* platform dependent support */ -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(strlen); - -/* PCI exports */ -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_alloc_consistent); -EXPORT_SYMBOL(pci_free_consistent); -#endif +#include <asm/sections.h> -/* mem exports */ EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); @@ -40,6 +14,13 @@ EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(csum_partial); +EXPORT_SYMBOL(csum_partial_copy_generic); +EXPORT_SYMBOL(copy_page); +EXPORT_SYMBOL(__clear_user); +EXPORT_SYMBOL(_ebss); +EXPORT_SYMBOL(empty_zero_page); #define DECLARE_EXPORT(name) \ extern void name(void);EXPORT_SYMBOL(name) @@ -107,30 +88,6 @@ DECLARE_EXPORT(__sdivsi3_i4); DECLARE_EXPORT(__udivsi3_i4); DECLARE_EXPORT(__sdivsi3_i4i); DECLARE_EXPORT(__udivsi3_i4i); - -#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ - defined(CONFIG_SH7705_CACHE_32KB)) -/* needed by some modules */ -EXPORT_SYMBOL(flush_cache_all); -EXPORT_SYMBOL(flush_cache_range); -EXPORT_SYMBOL(flush_dcache_page); -#endif - #ifdef CONFIG_MCOUNT DECLARE_EXPORT(mcount); #endif -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_generic); -#ifdef CONFIG_IPV6 -EXPORT_SYMBOL(csum_ipv6_magic); -#endif -EXPORT_SYMBOL(copy_page); -EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(_ebss); -EXPORT_SYMBOL(empty_zero_page); - -#ifndef CONFIG_CACHE_OFF -EXPORT_SYMBOL(__flush_purge_region); -EXPORT_SYMBOL(__flush_wback_region); -EXPORT_SYMBOL(__flush_invalidate_region); -#endif diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index d008e17eb257..45afa5c51f67 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -24,16 +24,6 @@ #include <asm/delay.h> #include <asm/irq.h> -extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); - -/* platform dependent support */ -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(kernel_thread); - -#ifdef CONFIG_VT -EXPORT_SYMBOL(screen_info); -#endif - EXPORT_SYMBOL(__put_user_asm_b); EXPORT_SYMBOL(__put_user_asm_w); EXPORT_SYMBOL(__put_user_asm_l); diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 3db37425210d..12815ce01ecd 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -67,7 +67,8 @@ sys_sigsuspend(old_sigset_t mask, current->state = TASK_INTERRUPTIBLE; schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); + return -ERESTARTNOHAND; } @@ -590,7 +591,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) if (try_to_freeze()) goto no_signal; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) + if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; @@ -602,12 +603,13 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &ka, &info, oldset, regs, save_r0) == 0) { - /* a signal was successfully delivered; the saved + /* + * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); + * clear the TS_RESTORE_SIGMASK flag + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; tracehook_signal_handler(signr, &info, &ka, regs, test_thread_flag(TIF_SINGLESTEP)); @@ -631,10 +633,12 @@ no_signal: } } - /* if there's no signal to deliver, we just put the saved sigmask - * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); + /* + * If there's no signal to deliver, we just put the saved sigmask + * back. + */ + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 74793c80a57a..feb3dddd3192 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -101,7 +101,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) if (try_to_freeze()) goto no_signal; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) + if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else if (!oldset) oldset = ¤t->blocked; @@ -115,11 +115,9 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) /* * If a signal was successfully delivered, the * saved sigmask is in its frame, and we can - * clear the TIF_RESTORE_SIGMASK flag. + * clear the TS_RESTORE_SIGMASK flag. */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; tracehook_signal_handler(signr, &info, &ka, regs, 0); return 1; } @@ -146,8 +144,8 @@ no_signal: } /* No signal to deliver -- put the saved sigmask back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } @@ -176,6 +174,7 @@ sys_sigsuspend(old_sigset_t mask, while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); + set_restore_sigmask(); regs->pc += 4; /* because sys_sigreturn decrements the pc */ if (do_signal(regs, &saveset)) { /* pc now points at signal handler. Need to decrement diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 160db1003cfb..983e0792d5f3 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -122,7 +122,9 @@ int __cpuinit __cpu_up(unsigned int cpu) stack_start.bss_start = 0; /* don't clear bss for secondary cpus */ stack_start.start_kernel_fn = start_secondary; - flush_cache_all(); + flush_icache_range((unsigned long)&stack_start, + (unsigned long)&stack_start + sizeof(stack_start)); + wmb(); plat_start_cpu(cpu, (unsigned long)_stext); diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c index 0838942b7083..9b0b633b6c92 100644 --- a/arch/sh/kernel/topology.c +++ b/arch/sh/kernel/topology.c @@ -16,6 +16,32 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); +cpumask_t cpu_core_map[NR_CPUS]; + +static cpumask_t cpu_coregroup_map(unsigned int cpu) +{ + /* + * Presently all SH-X3 SMP cores are multi-cores, so just keep it + * simple until we have a method for determining topology.. + */ + return cpu_possible_map; +} + +const struct cpumask *cpu_coregroup_mask(unsigned int cpu) +{ + return &cpu_core_map[cpu]; +} + +int arch_update_cpu_topology(void) +{ + unsigned int cpu; + + for_each_possible_cpu(cpu) + cpu_core_map[cpu] = cpu_coregroup_map(cpu); + + return 0; +} + static int __init topology_init(void) { int i, ret; diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index a8396f36bd14..7b036339dc92 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -9,8 +9,8 @@ #include <asm/unwinder.h> #include <asm/system.h> -#ifdef CONFIG_BUG -void handle_BUG(struct pt_regs *regs) +#ifdef CONFIG_GENERIC_BUG +static void handle_BUG(struct pt_regs *regs) { const struct bug_entry *bug; unsigned long bugaddr = regs->pc; @@ -81,7 +81,7 @@ BUILD_TRAP_HANDLER(bug) SIGTRAP) == NOTIFY_STOP) return; -#ifdef CONFIG_BUG +#ifdef CONFIG_GENERIC_BUG if (__kernel_text_address(instruction_pointer(regs))) { insn_size_t insn = *(insn_size_t *)instruction_pointer(regs); if (insn == TRAPA_BUG_OPCODE) @@ -95,9 +95,11 @@ BUILD_TRAP_HANDLER(bug) BUILD_TRAP_HANDLER(nmi) { + unsigned int cpu = smp_processor_id(); TRAP_HANDLER_DECL; nmi_enter(); + nmi_count(cpu)++; switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) { case NOTIFY_OK: diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 7a2ee3a6b8e7..3da5a125d884 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -25,6 +25,7 @@ #include <linux/kexec.h> #include <linux/limits.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/sysfs.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -68,61 +69,49 @@ static const char *se_usermode_action[] = { "signal+warn" }; -static int -proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int alignment_proc_show(struct seq_file *m, void *v) { - char *p = page; - int len; - - p += sprintf(p, "User:\t\t%lu\n", se_user); - p += sprintf(p, "System:\t\t%lu\n", se_sys); - p += sprintf(p, "Half:\t\t%lu\n", se_half); - p += sprintf(p, "Word:\t\t%lu\n", se_word); - p += sprintf(p, "DWord:\t\t%lu\n", se_dword); - p += sprintf(p, "Multi:\t\t%lu\n", se_multi); - p += sprintf(p, "User faults:\t%i (%s)\n", se_usermode, + seq_printf(m, "User:\t\t%lu\n", se_user); + seq_printf(m, "System:\t\t%lu\n", se_sys); + seq_printf(m, "Half:\t\t%lu\n", se_half); + seq_printf(m, "Word:\t\t%lu\n", se_word); + seq_printf(m, "DWord:\t\t%lu\n", se_dword); + seq_printf(m, "Multi:\t\t%lu\n", se_multi); + seq_printf(m, "User faults:\t%i (%s)\n", se_usermode, se_usermode_action[se_usermode]); - p += sprintf(p, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn, + seq_printf(m, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn, se_kernmode_warn ? "+warn" : ""); - - len = (p - page) - off; - if (len < 0) - len = 0; - - *eof = (len <= count) ? 1 : 0; - *start = page + off; - - return len; + return 0; } -static int proc_alignment_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int alignment_proc_open(struct inode *inode, struct file *file) { - char mode; - - if (count > 0) { - if (get_user(mode, buffer)) - return -EFAULT; - if (mode >= '0' && mode <= '5') - se_usermode = mode - '0'; - } - return count; + return single_open(file, alignment_proc_show, NULL); } -static int proc_alignment_kern_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t alignment_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { + int *data = PDE(file->f_path.dentry->d_inode)->data; char mode; if (count > 0) { if (get_user(mode, buffer)) return -EFAULT; - if (mode >= '0' && mode <= '1') - se_kernmode_warn = mode - '0'; + if (mode >= '0' && mode <= '5') + *data = mode - '0'; } return count; } + +static const struct file_operations alignment_proc_fops = { + .owner = THIS_MODULE, + .open = alignment_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = alignment_proc_write, +}; #endif static void dump_mem(const char *str, unsigned long bottom, unsigned long top) @@ -945,14 +934,9 @@ void __init trap_init(void) set_exception_table_evt(0x800, do_reserved_inst); set_exception_table_evt(0x820, do_illegal_slot_inst); #elif defined(CONFIG_SH_FPU) -#ifdef CONFIG_CPU_SUBTYPE_SHX3 - set_exception_table_evt(0xd80, fpu_state_restore_trap_handler); - set_exception_table_evt(0xda0, fpu_state_restore_trap_handler); -#else set_exception_table_evt(0x800, fpu_state_restore_trap_handler); set_exception_table_evt(0x820, fpu_state_restore_trap_handler); #endif -#endif #ifdef CONFIG_CPU_SH2 set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_trap_handler); @@ -1011,20 +995,16 @@ static int __init alignment_init(void) if (!dir) return -ENOMEM; - res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, dir); + res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir, + &alignment_proc_fops, &se_usermode); if (!res) return -ENOMEM; - res->read_proc = proc_alignment_read; - res->write_proc = proc_alignment_write; - - res = create_proc_entry("kernel_alignment", S_IWUSR | S_IRUGO, dir); + res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir, + &alignment_proc_fops, &se_kernmode_warn); if (!res) return -ENOMEM; - res->read_proc = proc_alignment_read; - res->write_proc = proc_alignment_kern_write; - return 0; } diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index a969b47c5463..dab4d2129812 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for SuperH-specific library files.. # -lib-y = delay.o memset.o memmove.o memchr.o \ +lib-y = delay.o memmove.o memchr.o \ checksum.o strlen.o div64.o div64-generic.o # Extracted from libgcc @@ -23,8 +23,11 @@ obj-y += io.o memcpy-y := memcpy.o memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o +memset-y := memset.o +memset-$(CONFIG_CPU_SH4) := memset-sh4.o + lib-$(CONFIG_MMU) += copy_page.o __clear_user.o lib-$(CONFIG_MCOUNT) += mcount.o -lib-y += $(memcpy-y) $(udivsi3-y) +lib-y += $(memcpy-y) $(memset-y) $(udivsi3-y) EXTRA_CFLAGS += -Werror diff --git a/arch/sh/lib/memset-sh4.S b/arch/sh/lib/memset-sh4.S new file mode 100644 index 000000000000..1a6e32cc4e4d --- /dev/null +++ b/arch/sh/lib/memset-sh4.S @@ -0,0 +1,107 @@ +/* + * "memset" implementation for SH4 + * + * Copyright (C) 1999 Niibe Yutaka + * Copyright (c) 2009 STMicroelectronics Limited + * Author: Stuart Menefy <stuart.menefy:st.com> + */ + +/* + * void *memset(void *s, int c, size_t n); + */ + +#include <linux/linkage.h> + +ENTRY(memset) + mov #12,r0 + add r6,r4 + cmp/gt r6,r0 + bt/s 40f ! if it's too small, set a byte at once + mov r4,r0 + and #3,r0 + cmp/eq #0,r0 + bt/s 2f ! It's aligned + sub r0,r6 +1: + dt r0 + bf/s 1b + mov.b r5,@-r4 +2: ! make VVVV + extu.b r5,r5 + swap.b r5,r0 ! V0 + or r0,r5 ! VV + swap.w r5,r0 ! VV00 + or r0,r5 ! VVVV + + ! Check if enough bytes need to be copied to be worth the big loop + mov #0x40, r0 ! (MT) + cmp/gt r6,r0 ! (MT) 64 > len => slow loop + + bt/s 22f + mov r6,r0 + + ! align the dst to the cache block size if necessary + mov r4, r3 + mov #~(0x1f), r1 + + and r3, r1 + cmp/eq r3, r1 + + bt/s 11f ! dst is already aligned + sub r1, r3 ! r3-r1 -> r3 + shlr2 r3 ! number of loops + +10: mov.l r5,@-r4 + dt r3 + bf/s 10b + add #-4, r6 + +11: ! dst is 32byte aligned + mov r6,r2 + mov #-5,r0 + shld r0,r2 ! number of loops + + add #-32, r4 + mov r5, r0 +12: + movca.l r0,@r4 + mov.l r5,@(4, r4) + mov.l r5,@(8, r4) + mov.l r5,@(12,r4) + mov.l r5,@(16,r4) + mov.l r5,@(20,r4) + add #-0x20, r6 + mov.l r5,@(24,r4) + dt r2 + mov.l r5,@(28,r4) + bf/s 12b + add #-32, r4 + + add #32, r4 + mov #8, r0 + cmp/ge r0, r6 + bf 40f + + mov r6,r0 +22: + shlr2 r0 + shlr r0 ! r0 = r6 >> 3 +3: + dt r0 + mov.l r5,@-r4 ! set 8-byte at once + bf/s 3b + mov.l r5,@-r4 + ! + mov #7,r0 + and r0,r6 + + ! fill bytes (length may be zero) +40: tst r6,r6 + bt 5f +4: + dt r6 + bf/s 4b + mov.b r5,@-r4 +5: + rts + mov r4,r0 diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c index ac2d7abd2567..d6c15cae0912 100644 --- a/arch/sh/math-emu/math.c +++ b/arch/sh/math-emu/math.c @@ -558,7 +558,7 @@ static int ieee_fpe_handler(struct pt_regs *regs) (finsn >> 8) & 0xf); tsk->thread.fpu.hard.fpscr &= ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); - set_tsk_thread_flag(tsk, TIF_USEDFPU); + task_thread_info(tsk)->status |= TS_USEDFPU; } else { info.si_signo = SIGFPE; info.si_errno = 0; @@ -619,10 +619,10 @@ int do_fpu_inst(unsigned short inst, struct pt_regs *regs) struct task_struct *tsk = current; struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft); - if (!test_tsk_thread_flag(tsk, TIF_USEDFPU)) { + if (!(task_thread_info(tsk)->status & TS_USEDFPU)) { /* initialize once. */ fpu_init(fpu); - set_tsk_thread_flag(tsk, TIF_USEDFPU); + task_thread_info(tsk)->status |= TS_USEDFPU; } return fpu_emulate(inst, fpu, regs); diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 7f7b52f9beba..0e7ba8e891cf 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -82,8 +82,7 @@ config 32BIT config PMB_ENABLE bool "Support 32-bit physical addressing through PMB" - depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7757 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785) - select 32BIT + depends on MMU && EXPERIMENTAL && CPU_SH4A default y help If you say Y here, physical addressing will be extended to @@ -97,8 +96,7 @@ choice config PMB bool "PMB" - depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7757 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785) - select 32BIT + depends on MMU && EXPERIMENTAL && CPU_SH4A help If you say Y here, physical addressing will be extended to 32-bits through the SH-4A PMB. If this is not set, legacy @@ -106,9 +104,7 @@ config PMB config PMB_FIXED bool "fixed PMB" - depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7757 || \ - CPU_SUBTYPE_SH7780 || \ - CPU_SUBTYPE_SH7785) + depends on MMU && EXPERIMENTAL && CPU_SH4A select 32BIT help If this option is enabled, fixed PMB mappings are inherited @@ -258,6 +254,15 @@ endchoice source "mm/Kconfig" +config SCHED_MC + bool "Multi-core scheduler support" + depends on SMP + default y + help + Multi-core scheduler support improves the CPU scheduler's decision + making when dealing with multi-core CPU chips at a cost of slightly + increased overhead in some places. If unsure say N here. + endmenu menu "Cache configuration" diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index 3759bf853293..8a70535fa7ce 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -33,8 +33,7 @@ obj-y += $(tlb-y) endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o -obj-$(CONFIG_PMB) += pmb.o -obj-$(CONFIG_PMB_FIXED) += pmb-fixed.o +obj-$(CONFIG_PMB_ENABLE) += pmb.o obj-$(CONFIG_NUMA) += numa.o # Special flags for fault_64.o. This puts restrictions on the number of diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index b7f235c74d66..f36a08bf3d5c 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -2,7 +2,7 @@ * arch/sh/mm/cache-sh4.c * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka - * Copyright (C) 2001 - 2007 Paul Mundt + * Copyright (C) 2001 - 2009 Paul Mundt * Copyright (C) 2003 Richard Curnow * Copyright (c) 2007 STMicroelectronics (R&D) Ltd. * @@ -15,6 +15,8 @@ #include <linux/io.h> #include <linux/mutex.h> #include <linux/fs.h> +#include <linux/highmem.h> +#include <asm/pgtable.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h> @@ -23,21 +25,12 @@ * flushing. Anything exceeding this will simply flush the dcache in its * entirety. */ -#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */ #define MAX_ICACHE_PAGES 32 static void __flush_cache_one(unsigned long addr, unsigned long phys, unsigned long exec_offset); /* - * This is initialised here to ensure that it is not placed in the BSS. If - * that were to happen, note that cache_init gets called before the BSS is - * cleared, so this would get nulled out which would be hopeless. - */ -static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) = - (void (*)(unsigned long, unsigned long))0xdeadbeef; - -/* * Write back the range of D-cache, and purge the I-cache. * * Called from kernel/module.c:sys_init_module and routine for a.out format, @@ -97,15 +90,15 @@ static inline void flush_cache_one(unsigned long start, unsigned long phys) unsigned long flags, exec_offset = 0; /* - * All types of SH-4 require PC to be in P2 to operate on the I-cache. - * Some types of SH-4 require PC to be in P2 to operate on the D-cache. + * All types of SH-4 require PC to be uncached to operate on the I-cache. + * Some types of SH-4 require PC to be uncached to operate on the D-cache. */ if ((boot_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) || (start < CACHE_OC_ADDRESS_ARRAY)) - exec_offset = 0x20000000; + exec_offset = cached_to_uncached; local_irq_save(flags); - __flush_cache_one(start | SH_CACHE_ASSOC, P1SEGADDR(phys), exec_offset); + __flush_cache_one(start, phys, exec_offset); local_irq_restore(flags); } @@ -124,7 +117,7 @@ static void sh4_flush_dcache_page(void *arg) else #endif { - unsigned long phys = PHYSADDR(page_address(page)); + unsigned long phys = page_to_phys(page); unsigned long addr = CACHE_OC_ADDRESS_ARRAY; int i, n; @@ -159,10 +152,27 @@ static void __uses_jump_to_uncached flush_icache_all(void) local_irq_restore(flags); } -static inline void flush_dcache_all(void) +static void flush_dcache_all(void) { - (*__flush_dcache_segment_fn)(0UL, boot_cpu_data.dcache.way_size); - wmb(); + unsigned long addr, end_addr, entry_offset; + + end_addr = CACHE_OC_ADDRESS_ARRAY + + (current_cpu_data.dcache.sets << + current_cpu_data.dcache.entry_shift) * + current_cpu_data.dcache.ways; + + entry_offset = 1 << current_cpu_data.dcache.entry_shift; + + for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; ) { + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + __raw_writel(0, addr); addr += entry_offset; + } } static void sh4_flush_cache_all(void *unused) @@ -171,89 +181,13 @@ static void sh4_flush_cache_all(void *unused) flush_icache_all(); } -static void __flush_cache_mm(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - unsigned long d = 0, p = start & PAGE_MASK; - unsigned long alias_mask = boot_cpu_data.dcache.alias_mask; - unsigned long n_aliases = boot_cpu_data.dcache.n_aliases; - unsigned long select_bit; - unsigned long all_aliases_mask; - unsigned long addr_offset; - pgd_t *dir; - pmd_t *pmd; - pud_t *pud; - pte_t *pte; - int i; - - dir = pgd_offset(mm, p); - pud = pud_offset(dir, p); - pmd = pmd_offset(pud, p); - end = PAGE_ALIGN(end); - - all_aliases_mask = (1 << n_aliases) - 1; - - do { - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) { - p &= PMD_MASK; - p += PMD_SIZE; - pmd++; - - continue; - } - - pte = pte_offset_kernel(pmd, p); - - do { - unsigned long phys; - pte_t entry = *pte; - - if (!(pte_val(entry) & _PAGE_PRESENT)) { - pte++; - p += PAGE_SIZE; - continue; - } - - phys = pte_val(entry) & PTE_PHYS_MASK; - - if ((p ^ phys) & alias_mask) { - d |= 1 << ((p & alias_mask) >> PAGE_SHIFT); - d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT); - - if (d == all_aliases_mask) - goto loop_exit; - } - - pte++; - p += PAGE_SIZE; - } while (p < end && ((unsigned long)pte & ~PAGE_MASK)); - pmd++; - } while (p < end); - -loop_exit: - addr_offset = 0; - select_bit = 1; - - for (i = 0; i < n_aliases; i++) { - if (d & select_bit) { - (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE); - wmb(); - } - - select_bit <<= 1; - addr_offset += PAGE_SIZE; - } -} - /* * Note : (RPC) since the caches are physically tagged, the only point * of flush_cache_mm for SH-4 is to get rid of aliases from the * D-cache. The assumption elsewhere, e.g. flush_cache_range, is that * lines can stay resident so long as the virtual address they were * accessed with (hence cache set) is in accord with the physical - * address (i.e. tag). It's no different here. So I reckon we don't - * need to flush the I-cache, since aliases don't matter for that. We - * should try that. + * address (i.e. tag). It's no different here. * * Caller takes mm->mmap_sem. */ @@ -264,33 +198,7 @@ static void sh4_flush_cache_mm(void *arg) if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT) return; - /* - * If cache is only 4k-per-way, there are never any 'aliases'. Since - * the cache is physically tagged, the data can just be left in there. - */ - if (boot_cpu_data.dcache.n_aliases == 0) - return; - - /* - * Don't bother groveling around the dcache for the VMA ranges - * if there are too many PTEs to make it worthwhile. - */ - if (mm->nr_ptes >= MAX_DCACHE_PAGES) - flush_dcache_all(); - else { - struct vm_area_struct *vma; - - /* - * In this case there are reasonably sized ranges to flush, - * iterate through the VMA list and take care of any aliases. - */ - for (vma = mm->mmap; vma; vma = vma->vm_next) - __flush_cache_mm(mm, vma->vm_start, vma->vm_end); - } - - /* Only touch the icache if one of the VMAs has VM_EXEC set. */ - if (mm->exec_vm) - flush_icache_all(); + flush_dcache_all(); } /* @@ -303,44 +211,63 @@ static void sh4_flush_cache_page(void *args) { struct flusher_data *data = args; struct vm_area_struct *vma; + struct page *page; unsigned long address, pfn, phys; - unsigned int alias_mask; + int map_coherent = 0; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + void *vaddr; vma = data->vma; - address = data->addr1; + address = data->addr1 & PAGE_MASK; pfn = data->addr2; phys = pfn << PAGE_SHIFT; + page = pfn_to_page(pfn); if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT) return; - alias_mask = boot_cpu_data.dcache.alias_mask; - - /* We only need to flush D-cache when we have alias */ - if ((address^phys) & alias_mask) { - /* Loop 4K of the D-cache */ - flush_cache_one( - CACHE_OC_ADDRESS_ARRAY | (address & alias_mask), - phys); - /* Loop another 4K of the D-cache */ - flush_cache_one( - CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask), - phys); - } + pgd = pgd_offset(vma->vm_mm, address); + pud = pud_offset(pgd, address); + pmd = pmd_offset(pud, address); + pte = pte_offset_kernel(pmd, address); + + /* If the page isn't present, there is nothing to do here. */ + if (!(pte_val(*pte) & _PAGE_PRESENT)) + return; - alias_mask = boot_cpu_data.icache.alias_mask; - if (vma->vm_flags & VM_EXEC) { + if ((vma->vm_mm == current->active_mm)) + vaddr = NULL; + else { /* - * Evict entries from the portion of the cache from which code - * may have been executed at this address (virtual). There's - * no need to evict from the portion corresponding to the - * physical address as for the D-cache, because we know the - * kernel has never executed the code through its identity - * translation. + * Use kmap_coherent or kmap_atomic to do flushes for + * another ASID than the current one. */ - flush_cache_one( - CACHE_IC_ADDRESS_ARRAY | (address & alias_mask), - phys); + map_coherent = (current_cpu_data.dcache.n_aliases && + !test_bit(PG_dcache_dirty, &page->flags) && + page_mapped(page)); + if (map_coherent) + vaddr = kmap_coherent(page, address); + else + vaddr = kmap_atomic(page, KM_USER0); + + address = (unsigned long)vaddr; + } + + if (pages_do_alias(address, phys)) + flush_cache_one(CACHE_OC_ADDRESS_ARRAY | + (address & shm_align_mask), phys); + + if (vma->vm_flags & VM_EXEC) + flush_icache_all(); + + if (vaddr) { + if (map_coherent) + kunmap_coherent(vaddr); + else + kunmap_atomic(vaddr, KM_USER0); } } @@ -373,24 +300,10 @@ static void sh4_flush_cache_range(void *args) if (boot_cpu_data.dcache.n_aliases == 0) return; - /* - * Don't bother with the lookup and alias check if we have a - * wide range to cover, just blow away the dcache in its - * entirety instead. -- PFM. - */ - if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES) - flush_dcache_all(); - else - __flush_cache_mm(vma->vm_mm, start, end); + flush_dcache_all(); - if (vma->vm_flags & VM_EXEC) { - /* - * TODO: Is this required??? Need to look at how I-cache - * coherency is assured when new programs are loaded to see if - * this matters. - */ + if (vma->vm_flags & VM_EXEC) flush_icache_all(); - } } /** @@ -464,245 +377,6 @@ static void __flush_cache_one(unsigned long addr, unsigned long phys, } while (--way_count != 0); } -/* - * Break the 1, 2 and 4 way variants of this out into separate functions to - * avoid nearly all the overhead of having the conditional stuff in the function - * bodies (+ the 1 and 2 way cases avoid saving any registers too). - * - * We want to eliminate unnecessary bus transactions, so this code uses - * a non-obvious technique. - * - * Loop over a cache way sized block of, one cache line at a time. For each - * line, use movca.a to cause the current cache line contents to be written - * back, but without reading anything from main memory. However this has the - * side effect that the cache is now caching that memory location. So follow - * this with a cache invalidate to mark the cache line invalid. And do all - * this with interrupts disabled, to avoid the cache line being accidently - * evicted while it is holding garbage. - * - * This also breaks in a number of circumstances: - * - if there are modifications to the region of memory just above - * empty_zero_page (for example because a breakpoint has been placed - * there), then these can be lost. - * - * This is because the the memory address which the cache temporarily - * caches in the above description is empty_zero_page. So the - * movca.l hits the cache (it is assumed that it misses, or at least - * isn't dirty), modifies the line and then invalidates it, losing the - * required change. - * - * - If caches are disabled or configured in write-through mode, then - * the movca.l writes garbage directly into memory. - */ -static void __flush_dcache_segment_writethrough(unsigned long start, - unsigned long extent_per_way) -{ - unsigned long addr; - int i; - - addr = CACHE_OC_ADDRESS_ARRAY | (start & cpu_data->dcache.entry_mask); - - while (extent_per_way) { - for (i = 0; i < cpu_data->dcache.ways; i++) - __raw_writel(0, addr + cpu_data->dcache.way_incr * i); - - addr += cpu_data->dcache.linesz; - extent_per_way -= cpu_data->dcache.linesz; - } -} - -static void __flush_dcache_segment_1way(unsigned long start, - unsigned long extent_per_way) -{ - unsigned long orig_sr, sr_with_bl; - unsigned long base_addr; - unsigned long way_incr, linesz, way_size; - struct cache_info *dcache; - register unsigned long a0, a0e; - - asm volatile("stc sr, %0" : "=r" (orig_sr)); - sr_with_bl = orig_sr | (1<<28); - base_addr = ((unsigned long)&empty_zero_page[0]); - - /* - * The previous code aligned base_addr to 16k, i.e. the way_size of all - * existing SH-4 D-caches. Whilst I don't see a need to have this - * aligned to any better than the cache line size (which it will be - * anyway by construction), let's align it to at least the way_size of - * any existing or conceivable SH-4 D-cache. -- RPC - */ - base_addr = ((base_addr >> 16) << 16); - base_addr |= start; - - dcache = &boot_cpu_data.dcache; - linesz = dcache->linesz; - way_incr = dcache->way_incr; - way_size = dcache->way_size; - - a0 = base_addr; - a0e = base_addr + extent_per_way; - do { - asm volatile("ldc %0, sr" : : "r" (sr_with_bl)); - asm volatile("movca.l r0, @%0\n\t" - "ocbi @%0" : : "r" (a0)); - a0 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "ocbi @%0" : : "r" (a0)); - a0 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "ocbi @%0" : : "r" (a0)); - a0 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "ocbi @%0" : : "r" (a0)); - asm volatile("ldc %0, sr" : : "r" (orig_sr)); - a0 += linesz; - } while (a0 < a0e); -} - -static void __flush_dcache_segment_2way(unsigned long start, - unsigned long extent_per_way) -{ - unsigned long orig_sr, sr_with_bl; - unsigned long base_addr; - unsigned long way_incr, linesz, way_size; - struct cache_info *dcache; - register unsigned long a0, a1, a0e; - - asm volatile("stc sr, %0" : "=r" (orig_sr)); - sr_with_bl = orig_sr | (1<<28); - base_addr = ((unsigned long)&empty_zero_page[0]); - - /* See comment under 1-way above */ - base_addr = ((base_addr >> 16) << 16); - base_addr |= start; - - dcache = &boot_cpu_data.dcache; - linesz = dcache->linesz; - way_incr = dcache->way_incr; - way_size = dcache->way_size; - - a0 = base_addr; - a1 = a0 + way_incr; - a0e = base_addr + extent_per_way; - do { - asm volatile("ldc %0, sr" : : "r" (sr_with_bl)); - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "ocbi @%0\n\t" - "ocbi @%1" : : - "r" (a0), "r" (a1)); - a0 += linesz; - a1 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "ocbi @%0\n\t" - "ocbi @%1" : : - "r" (a0), "r" (a1)); - a0 += linesz; - a1 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "ocbi @%0\n\t" - "ocbi @%1" : : - "r" (a0), "r" (a1)); - a0 += linesz; - a1 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "ocbi @%0\n\t" - "ocbi @%1" : : - "r" (a0), "r" (a1)); - asm volatile("ldc %0, sr" : : "r" (orig_sr)); - a0 += linesz; - a1 += linesz; - } while (a0 < a0e); -} - -static void __flush_dcache_segment_4way(unsigned long start, - unsigned long extent_per_way) -{ - unsigned long orig_sr, sr_with_bl; - unsigned long base_addr; - unsigned long way_incr, linesz, way_size; - struct cache_info *dcache; - register unsigned long a0, a1, a2, a3, a0e; - - asm volatile("stc sr, %0" : "=r" (orig_sr)); - sr_with_bl = orig_sr | (1<<28); - base_addr = ((unsigned long)&empty_zero_page[0]); - - /* See comment under 1-way above */ - base_addr = ((base_addr >> 16) << 16); - base_addr |= start; - - dcache = &boot_cpu_data.dcache; - linesz = dcache->linesz; - way_incr = dcache->way_incr; - way_size = dcache->way_size; - - a0 = base_addr; - a1 = a0 + way_incr; - a2 = a1 + way_incr; - a3 = a2 + way_incr; - a0e = base_addr + extent_per_way; - do { - asm volatile("ldc %0, sr" : : "r" (sr_with_bl)); - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "movca.l r0, @%2\n\t" - "movca.l r0, @%3\n\t" - "ocbi @%0\n\t" - "ocbi @%1\n\t" - "ocbi @%2\n\t" - "ocbi @%3\n\t" : : - "r" (a0), "r" (a1), "r" (a2), "r" (a3)); - a0 += linesz; - a1 += linesz; - a2 += linesz; - a3 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "movca.l r0, @%2\n\t" - "movca.l r0, @%3\n\t" - "ocbi @%0\n\t" - "ocbi @%1\n\t" - "ocbi @%2\n\t" - "ocbi @%3\n\t" : : - "r" (a0), "r" (a1), "r" (a2), "r" (a3)); - a0 += linesz; - a1 += linesz; - a2 += linesz; - a3 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "movca.l r0, @%2\n\t" - "movca.l r0, @%3\n\t" - "ocbi @%0\n\t" - "ocbi @%1\n\t" - "ocbi @%2\n\t" - "ocbi @%3\n\t" : : - "r" (a0), "r" (a1), "r" (a2), "r" (a3)); - a0 += linesz; - a1 += linesz; - a2 += linesz; - a3 += linesz; - asm volatile("movca.l r0, @%0\n\t" - "movca.l r0, @%1\n\t" - "movca.l r0, @%2\n\t" - "movca.l r0, @%3\n\t" - "ocbi @%0\n\t" - "ocbi @%1\n\t" - "ocbi @%2\n\t" - "ocbi @%3\n\t" : : - "r" (a0), "r" (a1), "r" (a2), "r" (a3)); - asm volatile("ldc %0, sr" : : "r" (orig_sr)); - a0 += linesz; - a1 += linesz; - a2 += linesz; - a3 += linesz; - } while (a0 < a0e); -} - extern void __weak sh4__flush_region_init(void); /* @@ -710,32 +384,11 @@ extern void __weak sh4__flush_region_init(void); */ void __init sh4_cache_init(void) { - unsigned int wt_enabled = !!(__raw_readl(CCR) & CCR_CACHE_WT); - printk("PVR=%08x CVR=%08x PRR=%08x\n", ctrl_inl(CCN_PVR), ctrl_inl(CCN_CVR), ctrl_inl(CCN_PRR)); - if (wt_enabled) - __flush_dcache_segment_fn = __flush_dcache_segment_writethrough; - else { - switch (boot_cpu_data.dcache.ways) { - case 1: - __flush_dcache_segment_fn = __flush_dcache_segment_1way; - break; - case 2: - __flush_dcache_segment_fn = __flush_dcache_segment_2way; - break; - case 4: - __flush_dcache_segment_fn = __flush_dcache_segment_4way; - break; - default: - panic("unknown number of cache ways\n"); - break; - } - } - local_flush_icache_range = sh4_flush_icache_range; local_flush_dcache_page = sh4_flush_dcache_page; local_flush_cache_all = sh4_flush_cache_all; diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c index 467ff8e260f7..eb4cc4ec7952 100644 --- a/arch/sh/mm/cache-sh5.c +++ b/arch/sh/mm/cache-sh5.c @@ -563,7 +563,7 @@ static void sh5_flush_cache_page(void *args) static void sh5_flush_dcache_page(void *page) { - sh64_dcache_purge_phy_page(page_to_phys(page)); + sh64_dcache_purge_phy_page(page_to_phys((struct page *)page)); wmb(); } diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c index 2601935eb589..f527fb70fce6 100644 --- a/arch/sh/mm/cache-sh7705.c +++ b/arch/sh/mm/cache-sh7705.c @@ -141,7 +141,7 @@ static void sh7705_flush_dcache_page(void *arg) if (mapping && !mapping_mapped(mapping)) set_bit(PG_dcache_dirty, &page->flags); else - __flush_dcache_page(PHYSADDR(page_address(page))); + __flush_dcache_page(__pa(page_address(page))); } static void __uses_jump_to_uncached sh7705_flush_cache_all(void *args) diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index a2dc7f9ecc51..e9415d3ea94a 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -27,8 +27,11 @@ void (*local_flush_icache_page)(void *args) = cache_noop; void (*local_flush_cache_sigtramp)(void *args) = cache_noop; void (*__flush_wback_region)(void *start, int size); +EXPORT_SYMBOL(__flush_wback_region); void (*__flush_purge_region)(void *start, int size); +EXPORT_SYMBOL(__flush_purge_region); void (*__flush_invalidate_region)(void *start, int size); +EXPORT_SYMBOL(__flush_invalidate_region); static inline void noop__flush_region(void *start, int size) { @@ -161,14 +164,21 @@ void flush_cache_all(void) { cacheop_on_each_cpu(local_flush_cache_all, NULL, 1); } +EXPORT_SYMBOL(flush_cache_all); void flush_cache_mm(struct mm_struct *mm) { + if (boot_cpu_data.dcache.n_aliases == 0) + return; + cacheop_on_each_cpu(local_flush_cache_mm, mm, 1); } void flush_cache_dup_mm(struct mm_struct *mm) { + if (boot_cpu_data.dcache.n_aliases == 0) + return; + cacheop_on_each_cpu(local_flush_cache_dup_mm, mm, 1); } @@ -195,11 +205,13 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, cacheop_on_each_cpu(local_flush_cache_range, (void *)&data, 1); } +EXPORT_SYMBOL(flush_cache_range); void flush_dcache_page(struct page *page) { cacheop_on_each_cpu(local_flush_dcache_page, page, 1); } +EXPORT_SYMBOL(flush_dcache_page); void flush_icache_range(unsigned long start, unsigned long end) { @@ -265,7 +277,11 @@ static void __init emit_cache_params(void) void __init cpu_cache_init(void) { - unsigned int cache_disabled = !(__raw_readl(CCR) & CCR_CACHE_ENABLE); + unsigned int cache_disabled = 0; + +#ifdef CCR + cache_disabled = !(__raw_readl(CCR) & CCR_CACHE_ENABLE); +#endif compute_alias(&boot_cpu_data.icache); compute_alias(&boot_cpu_data.dcache); diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index e098ec158ddb..902967e3f841 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -15,11 +15,15 @@ #include <linux/dma-mapping.h> #include <linux/dma-debug.h> #include <linux/io.h> +#include <linux/module.h> #include <asm/cacheflush.h> #include <asm/addrspace.h> #define PREALLOC_DMA_DEBUG_ENTRIES 4096 +struct dma_map_ops *dma_ops; +EXPORT_SYMBOL(dma_ops); + static int __init dma_init(void) { dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); @@ -27,15 +31,12 @@ static int __init dma_init(void) } fs_initcall(dma_init); -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) +void *dma_generic_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp) { void *ret, *ret_nocache; int order = get_order(size); - if (dma_alloc_from_coherent(dev, size, dma_handle, &ret)) - return ret; - ret = (void *)__get_free_pages(gfp, order); if (!ret) return NULL; @@ -57,35 +58,26 @@ void *dma_alloc_coherent(struct device *dev, size_t size, *dma_handle = virt_to_phys(ret); - debug_dma_alloc_coherent(dev, size, *dma_handle, ret_nocache); - return ret_nocache; } -EXPORT_SYMBOL(dma_alloc_coherent); -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) +void dma_generic_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) { int order = get_order(size); unsigned long pfn = dma_handle >> PAGE_SHIFT; int k; - WARN_ON(irqs_disabled()); /* for portability */ - - if (dma_release_from_coherent(dev, order, vaddr)) - return; - - debug_dma_free_coherent(dev, size, vaddr, dma_handle); for (k = 0; k < (1 << order); k++) __free_pages(pfn_to_page(pfn + k), 0); + iounmap(vaddr); } -EXPORT_SYMBOL(dma_free_coherent); void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { -#ifdef CONFIG_CPU_SH5 +#if defined(CONFIG_CPU_SH5) || defined(CONFIG_PMB) void *p1addr = vaddr; #else void *p1addr = (void*) P1SEGADDR((unsigned long)vaddr); diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 8173e38afd38..432acd07e76a 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -15,6 +15,7 @@ #include <linux/pagemap.h> #include <linux/percpu.h> #include <linux/io.h> +#include <linux/dma-mapping.h> #include <asm/mmu_context.h> #include <asm/tlb.h> #include <asm/cacheflush.h> @@ -186,11 +187,21 @@ void __init paging_init(void) set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start)); } +/* + * Early initialization for any I/O MMUs we might have. + */ +static void __init iommu_init(void) +{ + no_iommu_init(); +} + void __init mem_init(void) { int codesize, datasize, initsize; int nid; + iommu_init(); + num_physpages = 0; high_memory = NULL; @@ -323,4 +334,12 @@ int memory_add_physaddr_to_nid(u64 addr) } EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); #endif + #endif /* CONFIG_MEMORY_HOTPLUG */ + +#ifdef CONFIG_PMB +int __in_29bit_mode(void) +{ + return !(ctrl_inl(PMB_PASCR) & PASCR_SE); +} +#endif /* CONFIG_PMB */ diff --git a/arch/sh/mm/kmap.c b/arch/sh/mm/kmap.c index 16e01b5fed04..15d74ea42094 100644 --- a/arch/sh/mm/kmap.c +++ b/arch/sh/mm/kmap.c @@ -39,7 +39,9 @@ void *kmap_coherent(struct page *page, unsigned long addr) pagefault_disable(); idx = FIX_CMAP_END - - ((addr & current_cpu_data.dcache.alias_mask) >> PAGE_SHIFT); + (((addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1)) + + (FIX_N_COLOURS * smp_processor_id())); + vaddr = __fix_to_virt(idx); BUG_ON(!pte_none(*(kmap_coherent_pte - idx))); diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c index 9b784fdb947c..6c524446c0f6 100644 --- a/arch/sh/mm/numa.c +++ b/arch/sh/mm/numa.c @@ -60,7 +60,7 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end) unsigned long bootmem_paddr; /* Don't allow bogus node assignment */ - BUG_ON(nid > MAX_NUMNODES || nid == 0); + BUG_ON(nid > MAX_NUMNODES || nid <= 0); start_pfn = start >> PAGE_SHIFT; end_pfn = end >> PAGE_SHIFT; diff --git a/arch/sh/mm/pmb-fixed.c b/arch/sh/mm/pmb-fixed.c deleted file mode 100644 index 43c8eac4d8a1..000000000000 --- a/arch/sh/mm/pmb-fixed.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * arch/sh/mm/fixed_pmb.c - * - * Copyright (C) 2009 Renesas Solutions Corp. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/io.h> -#include <asm/mmu.h> -#include <asm/mmu_context.h> - -static int __uses_jump_to_uncached fixed_pmb_init(void) -{ - int i; - unsigned long addr, data; - - jump_to_uncached(); - - for (i = 0; i < PMB_ENTRY_MAX; i++) { - addr = PMB_DATA + (i << PMB_E_SHIFT); - data = ctrl_inl(addr); - if (!(data & PMB_V)) - continue; - - if (data & PMB_C) { -#if defined(CONFIG_CACHE_WRITETHROUGH) - data |= PMB_WT; -#elif defined(CONFIG_CACHE_WRITEBACK) - data &= ~PMB_WT; -#else - data &= ~(PMB_C | PMB_WT); -#endif - } - ctrl_outl(data, addr); - } - - back_to_cached(); - - return 0; -} -arch_initcall(fixed_pmb_init); diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index aade31102112..280f6a166035 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -35,29 +35,9 @@ static void __pmb_unmap(struct pmb_entry *); -static struct kmem_cache *pmb_cache; +static struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES]; static unsigned long pmb_map; -static struct pmb_entry pmb_init_map[] = { - /* vpn ppn flags (ub/sz/c/wt) */ - - /* P1 Section Mappings */ - { 0x80000000, 0x00000000, PMB_SZ_64M | PMB_C, }, - { 0x84000000, 0x04000000, PMB_SZ_64M | PMB_C, }, - { 0x88000000, 0x08000000, PMB_SZ_128M | PMB_C, }, - { 0x90000000, 0x10000000, PMB_SZ_64M | PMB_C, }, - { 0x94000000, 0x14000000, PMB_SZ_64M | PMB_C, }, - { 0x98000000, 0x18000000, PMB_SZ_64M | PMB_C, }, - - /* P2 Section Mappings */ - { 0xa0000000, 0x00000000, PMB_UB | PMB_SZ_64M | PMB_WT, }, - { 0xa4000000, 0x04000000, PMB_UB | PMB_SZ_64M | PMB_WT, }, - { 0xa8000000, 0x08000000, PMB_UB | PMB_SZ_128M | PMB_WT, }, - { 0xb0000000, 0x10000000, PMB_UB | PMB_SZ_64M | PMB_WT, }, - { 0xb4000000, 0x14000000, PMB_UB | PMB_SZ_64M | PMB_WT, }, - { 0xb8000000, 0x18000000, PMB_UB | PMB_SZ_64M | PMB_WT, }, -}; - static inline unsigned long mk_pmb_entry(unsigned int entry) { return (entry & PMB_E_MASK) << PMB_E_SHIFT; @@ -73,81 +53,68 @@ static inline unsigned long mk_pmb_data(unsigned int entry) return mk_pmb_entry(entry) | PMB_DATA; } -static DEFINE_SPINLOCK(pmb_list_lock); -static struct pmb_entry *pmb_list; - -static inline void pmb_list_add(struct pmb_entry *pmbe) +static int pmb_alloc_entry(void) { - struct pmb_entry **p, *tmp; + unsigned int pos; - p = &pmb_list; - while ((tmp = *p) != NULL) - p = &tmp->next; +repeat: + pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES); - pmbe->next = tmp; - *p = pmbe; -} + if (unlikely(pos > NR_PMB_ENTRIES)) + return -ENOSPC; -static inline void pmb_list_del(struct pmb_entry *pmbe) -{ - struct pmb_entry **p, *tmp; + if (test_and_set_bit(pos, &pmb_map)) + goto repeat; - for (p = &pmb_list; (tmp = *p); p = &tmp->next) - if (tmp == pmbe) { - *p = tmp->next; - return; - } + return pos; } -struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, - unsigned long flags) +static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn, + unsigned long flags, int entry) { struct pmb_entry *pmbe; + int pos; + + if (entry == PMB_NO_ENTRY) { + pos = pmb_alloc_entry(); + if (pos < 0) + return ERR_PTR(pos); + } else { + if (test_bit(entry, &pmb_map)) + return ERR_PTR(-ENOSPC); + pos = entry; + } - pmbe = kmem_cache_alloc(pmb_cache, GFP_KERNEL); + pmbe = &pmb_entry_list[pos]; if (!pmbe) return ERR_PTR(-ENOMEM); pmbe->vpn = vpn; pmbe->ppn = ppn; pmbe->flags = flags; - - spin_lock_irq(&pmb_list_lock); - pmb_list_add(pmbe); - spin_unlock_irq(&pmb_list_lock); + pmbe->entry = pos; return pmbe; } -void pmb_free(struct pmb_entry *pmbe) +static void pmb_free(struct pmb_entry *pmbe) { - spin_lock_irq(&pmb_list_lock); - pmb_list_del(pmbe); - spin_unlock_irq(&pmb_list_lock); + int pos = pmbe->entry; - kmem_cache_free(pmb_cache, pmbe); + pmbe->vpn = 0; + pmbe->ppn = 0; + pmbe->flags = 0; + pmbe->entry = 0; + + clear_bit(pos, &pmb_map); } /* * Must be in P2 for __set_pmb_entry() */ -int __set_pmb_entry(unsigned long vpn, unsigned long ppn, - unsigned long flags, int *entry) +static void __set_pmb_entry(unsigned long vpn, unsigned long ppn, + unsigned long flags, int pos) { - unsigned int pos = *entry; - - if (unlikely(pos == PMB_NO_ENTRY)) - pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES); - -repeat: - if (unlikely(pos > NR_PMB_ENTRIES)) - return -ENOSPC; - - if (test_and_set_bit(pos, &pmb_map)) { - pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES); - goto repeat; - } - ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos)); #ifdef CONFIG_CACHE_WRITETHROUGH @@ -161,35 +128,21 @@ repeat: #endif ctrl_outl(ppn | flags | PMB_V, mk_pmb_data(pos)); - - *entry = pos; - - return 0; } -int __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe) +static void __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe) { - int ret; - jump_to_uncached(); - ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry); + __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, pmbe->entry); back_to_cached(); - - return ret; } -void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe) +static void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe) { unsigned int entry = pmbe->entry; unsigned long addr; - /* - * Don't allow clearing of wired init entries, P1 or P2 access - * without a corresponding mapping in the PMB will lead to reset - * by the TLB. - */ - if (unlikely(entry < ARRAY_SIZE(pmb_init_map) || - entry >= NR_PMB_ENTRIES)) + if (unlikely(entry >= NR_PMB_ENTRIES)) return; jump_to_uncached(); @@ -202,8 +155,6 @@ void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe) ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr); back_to_cached(); - - clear_bit(entry, &pmb_map); } @@ -239,23 +190,17 @@ long pmb_remap(unsigned long vaddr, unsigned long phys, again: for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) { - int ret; - if (size < pmb_sizes[i].size) continue; - pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag); + pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag, + PMB_NO_ENTRY); if (IS_ERR(pmbe)) { err = PTR_ERR(pmbe); goto out; } - ret = set_pmb_entry(pmbe); - if (ret != 0) { - pmb_free(pmbe); - err = -EBUSY; - goto out; - } + set_pmb_entry(pmbe); phys += pmb_sizes[i].size; vaddr += pmb_sizes[i].size; @@ -292,11 +237,16 @@ out: void pmb_unmap(unsigned long addr) { - struct pmb_entry **p, *pmbe; + struct pmb_entry *pmbe = NULL; + int i; - for (p = &pmb_list; (pmbe = *p); p = &pmbe->next) - if (pmbe->vpn == addr) - break; + for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) { + if (test_bit(i, &pmb_map)) { + pmbe = &pmb_entry_list[i]; + if (pmbe->vpn == addr) + break; + } + } if (unlikely(!pmbe)) return; @@ -306,13 +256,22 @@ void pmb_unmap(unsigned long addr) static void __pmb_unmap(struct pmb_entry *pmbe) { - WARN_ON(!test_bit(pmbe->entry, &pmb_map)); + BUG_ON(!test_bit(pmbe->entry, &pmb_map)); do { struct pmb_entry *pmblink = pmbe; - if (pmbe->entry != PMB_NO_ENTRY) - clear_pmb_entry(pmbe); + /* + * We may be called before this pmb_entry has been + * entered into the PMB table via set_pmb_entry(), but + * that's OK because we've allocated a unique slot for + * this entry in pmb_alloc() (even if we haven't filled + * it yet). + * + * Therefore, calling clear_pmb_entry() is safe as no + * other mapping can be using that slot. + */ + clear_pmb_entry(pmbe); pmbe = pmblink->link; @@ -320,42 +279,34 @@ static void __pmb_unmap(struct pmb_entry *pmbe) } while (pmbe); } -static void pmb_cache_ctor(void *pmb) +#ifdef CONFIG_PMB +int __uses_jump_to_uncached pmb_init(void) { - struct pmb_entry *pmbe = pmb; - - memset(pmb, 0, sizeof(struct pmb_entry)); - - pmbe->entry = PMB_NO_ENTRY; -} - -static int __uses_jump_to_uncached pmb_init(void) -{ - unsigned int nr_entries = ARRAY_SIZE(pmb_init_map); - unsigned int entry, i; - - BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES)); - - pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0, - SLAB_PANIC, pmb_cache_ctor); + unsigned int i; + long size, ret; jump_to_uncached(); /* - * Ordering is important, P2 must be mapped in the PMB before we - * can set PMB.SE, and P1 must be mapped before we jump back to - * P1 space. + * Insert PMB entries for the P1 and P2 areas so that, after + * we've switched the MMU to 32-bit mode, the semantics of P1 + * and P2 are the same as in 29-bit mode, e.g. + * + * P1 - provides a cached window onto physical memory + * P2 - provides an uncached window onto physical memory */ - for (entry = 0; entry < nr_entries; entry++) { - struct pmb_entry *pmbe = pmb_init_map + entry; + size = __MEMORY_START + __MEMORY_SIZE; - __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &entry); - } + ret = pmb_remap(P1SEG, 0x00000000, size, PMB_C); + BUG_ON(ret != size); + + ret = pmb_remap(P2SEG, 0x00000000, size, PMB_WT | PMB_UB); + BUG_ON(ret != size); ctrl_outl(0, PMB_IRMCR); /* PMB.SE and UB[7] */ - ctrl_outl((1 << 31) | (1 << 7), PMB_PASCR); + ctrl_outl(PASCR_SE | (1 << 7), PMB_PASCR); /* Flush out the TLB */ i = ctrl_inl(MMUCR); @@ -366,7 +317,53 @@ static int __uses_jump_to_uncached pmb_init(void) return 0; } -arch_initcall(pmb_init); +#else +int __uses_jump_to_uncached pmb_init(void) +{ + int i; + unsigned long addr, data; + + jump_to_uncached(); + + for (i = 0; i < PMB_ENTRY_MAX; i++) { + struct pmb_entry *pmbe; + unsigned long vpn, ppn, flags; + + addr = PMB_DATA + (i << PMB_E_SHIFT); + data = ctrl_inl(addr); + if (!(data & PMB_V)) + continue; + + if (data & PMB_C) { +#if defined(CONFIG_CACHE_WRITETHROUGH) + data |= PMB_WT; +#elif defined(CONFIG_CACHE_WRITEBACK) + data &= ~PMB_WT; +#else + data &= ~(PMB_C | PMB_WT); +#endif + } + ctrl_outl(data, addr); + + ppn = data & PMB_PFN_MASK; + + flags = data & (PMB_C | PMB_WT | PMB_UB); + flags |= data & PMB_SZ_MASK; + + addr = PMB_ADDR + (i << PMB_E_SHIFT); + data = ctrl_inl(addr); + + vpn = data & PMB_PFN_MASK; + + pmbe = pmb_alloc(vpn, ppn, flags, i); + WARN_ON(IS_ERR(pmbe)); + } + + back_to_cached(); + + return 0; +} +#endif /* CONFIG_PMB */ static int pmb_seq_show(struct seq_file *file, void *iter) { @@ -434,15 +431,18 @@ postcore_initcall(pmb_debugfs_init); static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state) { static pm_message_t prev_state; + int i; /* Restore the PMB after a resume from hibernation */ if (state.event == PM_EVENT_ON && prev_state.event == PM_EVENT_FREEZE) { struct pmb_entry *pmbe; - spin_lock_irq(&pmb_list_lock); - for (pmbe = pmb_list; pmbe; pmbe = pmbe->next) - set_pmb_entry(pmbe); - spin_unlock_irq(&pmb_list_lock); + for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) { + if (test_bit(i, &pmb_map)) { + pmbe = &pmb_entry_list[i]; + set_pmb_entry(pmbe); + } + } } prev_state = state; return 0; diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile index 8e6eec91c14c..4886c5c1786c 100644 --- a/arch/sh/oprofile/Makefile +++ b/arch/sh/oprofile/Makefile @@ -7,7 +7,3 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) oprofile-y := $(DRIVER_OBJS) common.o backtrace.o - -oprofile-$(CONFIG_CPU_SUBTYPE_SH7750S) += op_model_sh7750.o -oprofile-$(CONFIG_CPU_SUBTYPE_SH7750) += op_model_sh7750.o -oprofile-$(CONFIG_CPU_SUBTYPE_SH7091) += op_model_sh7750.o diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c index 44f4e31c6d63..ac604937f3ee 100644 --- a/arch/sh/oprofile/common.c +++ b/arch/sh/oprofile/common.c @@ -20,9 +20,6 @@ #include <asm/processor.h> #include "op_impl.h" -extern struct op_sh_model op_model_sh7750_ops __weak; -extern struct op_sh_model op_model_sh4a_ops __weak; - static struct op_sh_model *model; static struct op_counter_config ctr[20]; @@ -94,33 +91,14 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) */ ops->backtrace = sh_backtrace; - switch (current_cpu_data.type) { - /* SH-4 types */ - case CPU_SH7750: - case CPU_SH7750S: - lmodel = &op_model_sh7750_ops; - break; - - /* SH-4A types */ - case CPU_SH7763: - case CPU_SH7770: - case CPU_SH7780: - case CPU_SH7781: - case CPU_SH7785: - case CPU_SH7786: - case CPU_SH7723: - case CPU_SH7724: - case CPU_SHX3: - lmodel = &op_model_sh4a_ops; - break; - - /* SH4AL-DSP types */ - case CPU_SH7343: - case CPU_SH7722: - case CPU_SH7366: - lmodel = &op_model_sh4a_ops; - break; - } + /* + * XXX + * + * All of the SH7750/SH-4A counters have been converted to perf, + * this infrastructure hook is left for other users until they've + * had a chance to convert over, at which point all of this + * will be deleted. + */ if (!lmodel) return -ENODEV; diff --git a/arch/sh/oprofile/op_impl.h b/arch/sh/oprofile/op_impl.h index 4d509975eba6..1244479ceb29 100644 --- a/arch/sh/oprofile/op_impl.h +++ b/arch/sh/oprofile/op_impl.h @@ -6,7 +6,7 @@ struct op_counter_config { unsigned long enabled; unsigned long event; - unsigned long long count; + unsigned long count; /* Dummy values for userspace tool compliance */ unsigned long kernel; diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c deleted file mode 100644 index c892c7c30c2f..000000000000 --- a/arch/sh/oprofile/op_model_sh7750.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * arch/sh/oprofile/op_model_sh7750.c - * - * OProfile support for SH7750/SH7750S Performance Counters - * - * Copyright (C) 2003 - 2008 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/kernel.h> -#include <linux/oprofile.h> -#include <linux/profile.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/fs.h> -#include "op_impl.h" - -#define PM_CR_BASE 0xff000084 /* 16-bit */ -#define PM_CTR_BASE 0xff100004 /* 32-bit */ - -#define PMCR(n) (PM_CR_BASE + ((n) * 0x04)) -#define PMCTRH(n) (PM_CTR_BASE + 0x00 + ((n) * 0x08)) -#define PMCTRL(n) (PM_CTR_BASE + 0x04 + ((n) * 0x08)) - -#define PMCR_PMM_MASK 0x0000003f - -#define PMCR_CLKF 0x00000100 -#define PMCR_PMCLR 0x00002000 -#define PMCR_PMST 0x00004000 -#define PMCR_PMEN 0x00008000 - -struct op_sh_model op_model_sh7750_ops; - -#define NR_CNTRS 2 - -static struct sh7750_ppc_register_config { - unsigned int ctrl; - unsigned long cnt_hi; - unsigned long cnt_lo; -} regcache[NR_CNTRS]; - -/* - * There are a number of events supported by each counter (33 in total). - * Since we have 2 counters, each counter will take the event code as it - * corresponds to the PMCR PMM setting. Each counter can be configured - * independently. - * - * Event Code Description - * ---------- ----------- - * - * 0x01 Operand read access - * 0x02 Operand write access - * 0x03 UTLB miss - * 0x04 Operand cache read miss - * 0x05 Operand cache write miss - * 0x06 Instruction fetch (w/ cache) - * 0x07 Instruction TLB miss - * 0x08 Instruction cache miss - * 0x09 All operand accesses - * 0x0a All instruction accesses - * 0x0b OC RAM operand access - * 0x0d On-chip I/O space access - * 0x0e Operand access (r/w) - * 0x0f Operand cache miss (r/w) - * 0x10 Branch instruction - * 0x11 Branch taken - * 0x12 BSR/BSRF/JSR - * 0x13 Instruction execution - * 0x14 Instruction execution in parallel - * 0x15 FPU Instruction execution - * 0x16 Interrupt - * 0x17 NMI - * 0x18 trapa instruction execution - * 0x19 UBCA match - * 0x1a UBCB match - * 0x21 Instruction cache fill - * 0x22 Operand cache fill - * 0x23 Elapsed time - * 0x24 Pipeline freeze by I-cache miss - * 0x25 Pipeline freeze by D-cache miss - * 0x27 Pipeline freeze by branch instruction - * 0x28 Pipeline freeze by CPU register - * 0x29 Pipeline freeze by FPU - * - * Unfortunately we don't have a native exception or interrupt for counter - * overflow (although since these counters can run for 16.3 days without - * overflowing, it's not really necessary). - * - * OProfile on the other hand likes to have samples taken periodically, so - * for now we just piggyback the timer interrupt to get the expected - * behavior. - */ - -static int sh7750_timer_notify(struct pt_regs *regs) -{ - oprofile_add_sample(regs, 0); - return 0; -} - -static u64 sh7750_read_counter(int counter) -{ - return (u64)((u64)(__raw_readl(PMCTRH(counter)) & 0xffff) << 32) | - __raw_readl(PMCTRL(counter)); -} - -/* - * Files will be in a path like: - * - * /<oprofilefs mount point>/<counter number>/<file> - * - * So when dealing with <file>, we look to the parent dentry for the counter - * number. - */ -static inline int to_counter(struct file *file) -{ - const unsigned char *name = file->f_path.dentry->d_parent->d_name.name; - - return (int)simple_strtol(name, NULL, 10); -} - -/* - * XXX: We have 48-bit counters, so we're probably going to want something - * more along the lines of oprofilefs_ullong_to_user().. Truncating to - * unsigned long works fine for now though, as long as we don't attempt to - * profile for too horribly long. - */ -static ssize_t sh7750_read_count(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int counter = to_counter(file); - u64 val = sh7750_read_counter(counter); - - return oprofilefs_ulong_to_user((unsigned long)val, buf, count, ppos); -} - -static ssize_t sh7750_write_count(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int counter = to_counter(file); - unsigned long val; - - if (oprofilefs_ulong_from_user(&val, buf, count)) - return -EFAULT; - - /* - * Any write will clear the counter, although only 0 should be - * written for this purpose, as we do not support setting the - * counter to an arbitrary value. - */ - WARN_ON(val != 0); - - __raw_writew(__raw_readw(PMCR(counter)) | PMCR_PMCLR, PMCR(counter)); - - return count; -} - -static const struct file_operations count_fops = { - .read = sh7750_read_count, - .write = sh7750_write_count, -}; - -static int sh7750_ppc_create_files(struct super_block *sb, struct dentry *dir) -{ - return oprofilefs_create_file(sb, dir, "count", &count_fops); -} - -static void sh7750_ppc_reg_setup(struct op_counter_config *ctr) -{ - unsigned int counters = op_model_sh7750_ops.num_counters; - int i; - - for (i = 0; i < counters; i++) { - regcache[i].ctrl = 0; - regcache[i].cnt_hi = 0; - regcache[i].cnt_lo = 0; - - if (!ctr[i].enabled) - continue; - - regcache[i].ctrl |= ctr[i].event | PMCR_PMEN | PMCR_PMST; - regcache[i].cnt_hi = (unsigned long)((ctr->count >> 32) & 0xffff); - regcache[i].cnt_lo = (unsigned long)(ctr->count & 0xffffffff); - } -} - -static void sh7750_ppc_cpu_setup(void *args) -{ - unsigned int counters = op_model_sh7750_ops.num_counters; - int i; - - for (i = 0; i < counters; i++) { - __raw_writew(0, PMCR(i)); - __raw_writel(regcache[i].cnt_hi, PMCTRH(i)); - __raw_writel(regcache[i].cnt_lo, PMCTRL(i)); - } -} - -static void sh7750_ppc_cpu_start(void *args) -{ - unsigned int counters = op_model_sh7750_ops.num_counters; - int i; - - for (i = 0; i < counters; i++) - __raw_writew(regcache[i].ctrl, PMCR(i)); -} - -static void sh7750_ppc_cpu_stop(void *args) -{ - unsigned int counters = op_model_sh7750_ops.num_counters; - int i; - - /* Disable the counters */ - for (i = 0; i < counters; i++) - __raw_writew(__raw_readw(PMCR(i)) & ~PMCR_PMEN, PMCR(i)); -} - -static inline void sh7750_ppc_reset(void) -{ - unsigned int counters = op_model_sh7750_ops.num_counters; - int i; - - /* Clear the counters */ - for (i = 0; i < counters; i++) - __raw_writew(__raw_readw(PMCR(i)) | PMCR_PMCLR, PMCR(i)); -} - -static int sh7750_ppc_init(void) -{ - sh7750_ppc_reset(); - - return register_timer_hook(sh7750_timer_notify); -} - -static void sh7750_ppc_exit(void) -{ - unregister_timer_hook(sh7750_timer_notify); - - sh7750_ppc_reset(); -} - -struct op_sh_model op_model_sh7750_ops = { - .cpu_type = "sh/sh7750", - .num_counters = NR_CNTRS, - .reg_setup = sh7750_ppc_reg_setup, - .cpu_setup = sh7750_ppc_cpu_setup, - .cpu_start = sh7750_ppc_cpu_start, - .cpu_stop = sh7750_ppc_cpu_stop, - .init = sh7750_ppc_init, - .exit = sh7750_ppc_exit, - .create_files = sh7750_ppc_create_files, -}; diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index da1218e8ee87..63f73ae8a892 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -847,7 +847,7 @@ void __init time_init(void) sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); - printk("clockevent: mult[%lx] shift[%d]\n", + printk("clockevent: mult[%ux] shift[%d]\n", sparc64_clockevent.mult, sparc64_clockevent.shift); setup_sparc64_timer(); diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index eb240323c40a..d22f9e5c0eac 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -16,7 +16,7 @@ #include <linux/miscdevice.h> #include <linux/module.h> #include <linux/mm.h> -#include <linux/smp_lock.h> + #include <asm/uaccess.h> #include "mem_user.h" @@ -78,7 +78,6 @@ out: static int mmapper_open(struct inode *inode, struct file *file) { - cycle_kernel_lock(); return 0; } @@ -115,18 +114,16 @@ static int __init mmapper_init(void) v_buf = (char *) find_iomem("mmapper", &mmapper_size); if (mmapper_size == 0) { printk(KERN_ERR "mmapper_init - find_iomem failed\n"); - goto out; + return -ENODEV; } + p_buf = __pa(v_buf); err = misc_register(&mmapper_dev); if (err) { printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", err); - goto out; + return err;; } - - p_buf = __pa(v_buf); -out: return 0; } diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 6eabb7022a2d..4949044773ba 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -7,7 +7,6 @@ * of the GNU General Public License, incorporated herein by reference. */ #include <linux/sched.h> -#include <linux/smp_lock.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/interrupt.h> @@ -34,8 +33,6 @@ static DECLARE_WAIT_QUEUE_HEAD(host_read_wait); static int rng_dev_open (struct inode *inode, struct file *filp) { - cycle_kernel_lock(); - /* enforce read-only access to this chrdev */ if ((filp->f_mode & FMODE_READ) == 0) return -EINVAL; diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index cfb0010fa940..1a58ad89fdf7 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o +obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o @@ -24,3 +25,5 @@ twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o + +ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index eb0566e83319..20bb0e1ac681 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -16,6 +16,7 @@ */ #include <linux/linkage.h> +#include <asm/inst.h> .text @@ -122,103 +123,72 @@ ENTRY(aesni_set_key) movups 0x10(%rsi), %xmm2 # other user key movaps %xmm2, (%rcx) add $0x10, %rcx - # aeskeygenassist $0x1, %xmm2, %xmm1 # round 1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x01 + AESKEYGENASSIST 0x1 %xmm2 %xmm1 # round 1 call _key_expansion_256a - # aeskeygenassist $0x1, %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x01 + AESKEYGENASSIST 0x1 %xmm0 %xmm1 call _key_expansion_256b - # aeskeygenassist $0x2, %xmm2, %xmm1 # round 2 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x02 + AESKEYGENASSIST 0x2 %xmm2 %xmm1 # round 2 call _key_expansion_256a - # aeskeygenassist $0x2, %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x02 + AESKEYGENASSIST 0x2 %xmm0 %xmm1 call _key_expansion_256b - # aeskeygenassist $0x4, %xmm2, %xmm1 # round 3 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x04 + AESKEYGENASSIST 0x4 %xmm2 %xmm1 # round 3 call _key_expansion_256a - # aeskeygenassist $0x4, %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x04 + AESKEYGENASSIST 0x4 %xmm0 %xmm1 call _key_expansion_256b - # aeskeygenassist $0x8, %xmm2, %xmm1 # round 4 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x08 + AESKEYGENASSIST 0x8 %xmm2 %xmm1 # round 4 call _key_expansion_256a - # aeskeygenassist $0x8, %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x08 + AESKEYGENASSIST 0x8 %xmm0 %xmm1 call _key_expansion_256b - # aeskeygenassist $0x10, %xmm2, %xmm1 # round 5 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x10 + AESKEYGENASSIST 0x10 %xmm2 %xmm1 # round 5 call _key_expansion_256a - # aeskeygenassist $0x10, %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x10 + AESKEYGENASSIST 0x10 %xmm0 %xmm1 call _key_expansion_256b - # aeskeygenassist $0x20, %xmm2, %xmm1 # round 6 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x20 + AESKEYGENASSIST 0x20 %xmm2 %xmm1 # round 6 call _key_expansion_256a - # aeskeygenassist $0x20, %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x20 + AESKEYGENASSIST 0x20 %xmm0 %xmm1 call _key_expansion_256b - # aeskeygenassist $0x40, %xmm2, %xmm1 # round 7 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x40 + AESKEYGENASSIST 0x40 %xmm2 %xmm1 # round 7 call _key_expansion_256a jmp .Ldec_key .Lenc_key192: movq 0x10(%rsi), %xmm2 # other user key - # aeskeygenassist $0x1, %xmm2, %xmm1 # round 1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x01 + AESKEYGENASSIST 0x1 %xmm2 %xmm1 # round 1 call _key_expansion_192a - # aeskeygenassist $0x2, %xmm2, %xmm1 # round 2 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x02 + AESKEYGENASSIST 0x2 %xmm2 %xmm1 # round 2 call _key_expansion_192b - # aeskeygenassist $0x4, %xmm2, %xmm1 # round 3 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x04 + AESKEYGENASSIST 0x4 %xmm2 %xmm1 # round 3 call _key_expansion_192a - # aeskeygenassist $0x8, %xmm2, %xmm1 # round 4 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x08 + AESKEYGENASSIST 0x8 %xmm2 %xmm1 # round 4 call _key_expansion_192b - # aeskeygenassist $0x10, %xmm2, %xmm1 # round 5 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x10 + AESKEYGENASSIST 0x10 %xmm2 %xmm1 # round 5 call _key_expansion_192a - # aeskeygenassist $0x20, %xmm2, %xmm1 # round 6 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x20 + AESKEYGENASSIST 0x20 %xmm2 %xmm1 # round 6 call _key_expansion_192b - # aeskeygenassist $0x40, %xmm2, %xmm1 # round 7 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x40 + AESKEYGENASSIST 0x40 %xmm2 %xmm1 # round 7 call _key_expansion_192a - # aeskeygenassist $0x80, %xmm2, %xmm1 # round 8 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x80 + AESKEYGENASSIST 0x80 %xmm2 %xmm1 # round 8 call _key_expansion_192b jmp .Ldec_key .Lenc_key128: - # aeskeygenassist $0x1, %xmm0, %xmm1 # round 1 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x01 + AESKEYGENASSIST 0x1 %xmm0 %xmm1 # round 1 call _key_expansion_128 - # aeskeygenassist $0x2, %xmm0, %xmm1 # round 2 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x02 + AESKEYGENASSIST 0x2 %xmm0 %xmm1 # round 2 call _key_expansion_128 - # aeskeygenassist $0x4, %xmm0, %xmm1 # round 3 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x04 + AESKEYGENASSIST 0x4 %xmm0 %xmm1 # round 3 call _key_expansion_128 - # aeskeygenassist $0x8, %xmm0, %xmm1 # round 4 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x08 + AESKEYGENASSIST 0x8 %xmm0 %xmm1 # round 4 call _key_expansion_128 - # aeskeygenassist $0x10, %xmm0, %xmm1 # round 5 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x10 + AESKEYGENASSIST 0x10 %xmm0 %xmm1 # round 5 call _key_expansion_128 - # aeskeygenassist $0x20, %xmm0, %xmm1 # round 6 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x20 + AESKEYGENASSIST 0x20 %xmm0 %xmm1 # round 6 call _key_expansion_128 - # aeskeygenassist $0x40, %xmm0, %xmm1 # round 7 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x40 + AESKEYGENASSIST 0x40 %xmm0 %xmm1 # round 7 call _key_expansion_128 - # aeskeygenassist $0x80, %xmm0, %xmm1 # round 8 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x80 + AESKEYGENASSIST 0x80 %xmm0 %xmm1 # round 8 call _key_expansion_128 - # aeskeygenassist $0x1b, %xmm0, %xmm1 # round 9 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x1b + AESKEYGENASSIST 0x1b %xmm0 %xmm1 # round 9 call _key_expansion_128 - # aeskeygenassist $0x36, %xmm0, %xmm1 # round 10 - .byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x36 + AESKEYGENASSIST 0x36 %xmm0 %xmm1 # round 10 call _key_expansion_128 .Ldec_key: sub $0x10, %rcx @@ -231,8 +201,7 @@ ENTRY(aesni_set_key) .align 4 .Ldec_key_loop: movaps (%rdi), %xmm0 - # aesimc %xmm0, %xmm1 - .byte 0x66, 0x0f, 0x38, 0xdb, 0xc8 + AESIMC %xmm0 %xmm1 movaps %xmm1, (%rsi) add $0x10, %rdi sub $0x10, %rsi @@ -274,51 +243,37 @@ _aesni_enc1: je .Lenc192 add $0x20, TKEYP movaps -0x60(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps -0x50(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE .align 4 .Lenc192: movaps -0x40(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps -0x30(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE .align 4 .Lenc128: movaps -0x20(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps -0x10(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps (TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x10(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x20(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x30(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x40(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x50(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x60(TKEYP), KEY - # aesenc KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 + AESENC KEY STATE movaps 0x70(TKEYP), KEY - # aesenclast KEY, STATE # last round - .byte 0x66, 0x0f, 0x38, 0xdd, 0xc2 + AESENCLAST KEY STATE ret /* @@ -353,135 +308,79 @@ _aesni_enc4: je .L4enc192 add $0x20, TKEYP movaps -0x60(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps -0x50(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 #.align 4 .L4enc192: movaps -0x40(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps -0x30(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 #.align 4 .L4enc128: movaps -0x20(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps -0x10(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps (TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x10(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x20(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x30(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x40(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x50(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x60(TKEYP), KEY - # aesenc KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xc2 - # aesenc KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xe2 - # aesenc KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xea - # aesenc KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdc, 0xf2 + AESENC KEY STATE1 + AESENC KEY STATE2 + AESENC KEY STATE3 + AESENC KEY STATE4 movaps 0x70(TKEYP), KEY - # aesenclast KEY, STATE1 # last round - .byte 0x66, 0x0f, 0x38, 0xdd, 0xc2 - # aesenclast KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdd, 0xe2 - # aesenclast KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdd, 0xea - # aesenclast KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdd, 0xf2 + AESENCLAST KEY STATE1 # last round + AESENCLAST KEY STATE2 + AESENCLAST KEY STATE3 + AESENCLAST KEY STATE4 ret /* @@ -518,51 +417,37 @@ _aesni_dec1: je .Ldec192 add $0x20, TKEYP movaps -0x60(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps -0x50(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE .align 4 .Ldec192: movaps -0x40(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps -0x30(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE .align 4 .Ldec128: movaps -0x20(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps -0x10(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps (TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x10(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x20(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x30(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x40(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x50(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x60(TKEYP), KEY - # aesdec KEY, STATE - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 + AESDEC KEY STATE movaps 0x70(TKEYP), KEY - # aesdeclast KEY, STATE # last round - .byte 0x66, 0x0f, 0x38, 0xdf, 0xc2 + AESDECLAST KEY STATE ret /* @@ -597,135 +482,79 @@ _aesni_dec4: je .L4dec192 add $0x20, TKEYP movaps -0x60(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps -0x50(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 .align 4 .L4dec192: movaps -0x40(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps -0x30(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 .align 4 .L4dec128: movaps -0x20(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps -0x10(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps (TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x10(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x20(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x30(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x40(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x50(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x60(TKEYP), KEY - # aesdec KEY, STATE1 - .byte 0x66, 0x0f, 0x38, 0xde, 0xc2 - # aesdec KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xde, 0xe2 - # aesdec KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xde, 0xea - # aesdec KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xde, 0xf2 + AESDEC KEY STATE1 + AESDEC KEY STATE2 + AESDEC KEY STATE3 + AESDEC KEY STATE4 movaps 0x70(TKEYP), KEY - # aesdeclast KEY, STATE1 # last round - .byte 0x66, 0x0f, 0x38, 0xdf, 0xc2 - # aesdeclast KEY, STATE2 - .byte 0x66, 0x0f, 0x38, 0xdf, 0xe2 - # aesdeclast KEY, STATE3 - .byte 0x66, 0x0f, 0x38, 0xdf, 0xea - # aesdeclast KEY, STATE4 - .byte 0x66, 0x0f, 0x38, 0xdf, 0xf2 + AESDECLAST KEY STATE1 # last round + AESDECLAST KEY STATE2 + AESDECLAST KEY STATE3 + AESDECLAST KEY STATE4 ret /* diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S new file mode 100644 index 000000000000..1eb7f90cb7b9 --- /dev/null +++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S @@ -0,0 +1,157 @@ +/* + * Accelerated GHASH implementation with Intel PCLMULQDQ-NI + * instructions. This file contains accelerated part of ghash + * implementation. More information about PCLMULQDQ can be found at: + * + * http://software.intel.com/en-us/articles/carry-less-multiplication-and-its-usage-for-computing-the-gcm-mode/ + * + * Copyright (c) 2009 Intel Corp. + * Author: Huang Ying <ying.huang@intel.com> + * Vinodh Gopal + * Erdinc Ozturk + * Deniz Karakoyunlu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/linkage.h> +#include <asm/inst.h> + +.data + +.align 16 +.Lbswap_mask: + .octa 0x000102030405060708090a0b0c0d0e0f +.Lpoly: + .octa 0xc2000000000000000000000000000001 +.Ltwo_one: + .octa 0x00000001000000000000000000000001 + +#define DATA %xmm0 +#define SHASH %xmm1 +#define T1 %xmm2 +#define T2 %xmm3 +#define T3 %xmm4 +#define BSWAP %xmm5 +#define IN1 %xmm6 + +.text + +/* + * __clmul_gf128mul_ble: internal ABI + * input: + * DATA: operand1 + * SHASH: operand2, hash_key << 1 mod poly + * output: + * DATA: operand1 * operand2 mod poly + * changed: + * T1 + * T2 + * T3 + */ +__clmul_gf128mul_ble: + movaps DATA, T1 + pshufd $0b01001110, DATA, T2 + pshufd $0b01001110, SHASH, T3 + pxor DATA, T2 + pxor SHASH, T3 + + PCLMULQDQ 0x00 SHASH DATA # DATA = a0 * b0 + PCLMULQDQ 0x11 SHASH T1 # T1 = a1 * b1 + PCLMULQDQ 0x00 T3 T2 # T2 = (a1 + a0) * (b1 + b0) + pxor DATA, T2 + pxor T1, T2 # T2 = a0 * b1 + a1 * b0 + + movaps T2, T3 + pslldq $8, T3 + psrldq $8, T2 + pxor T3, DATA + pxor T2, T1 # <T1:DATA> is result of + # carry-less multiplication + + # first phase of the reduction + movaps DATA, T3 + psllq $1, T3 + pxor DATA, T3 + psllq $5, T3 + pxor DATA, T3 + psllq $57, T3 + movaps T3, T2 + pslldq $8, T2 + psrldq $8, T3 + pxor T2, DATA + pxor T3, T1 + + # second phase of the reduction + movaps DATA, T2 + psrlq $5, T2 + pxor DATA, T2 + psrlq $1, T2 + pxor DATA, T2 + psrlq $1, T2 + pxor T2, T1 + pxor T1, DATA + ret + +/* void clmul_ghash_mul(char *dst, const be128 *shash) */ +ENTRY(clmul_ghash_mul) + movups (%rdi), DATA + movups (%rsi), SHASH + movaps .Lbswap_mask, BSWAP + PSHUFB_XMM BSWAP DATA + call __clmul_gf128mul_ble + PSHUFB_XMM BSWAP DATA + movups DATA, (%rdi) + ret + +/* + * void clmul_ghash_update(char *dst, const char *src, unsigned int srclen, + * const be128 *shash); + */ +ENTRY(clmul_ghash_update) + cmp $16, %rdx + jb .Lupdate_just_ret # check length + movaps .Lbswap_mask, BSWAP + movups (%rdi), DATA + movups (%rcx), SHASH + PSHUFB_XMM BSWAP DATA +.align 4 +.Lupdate_loop: + movups (%rsi), IN1 + PSHUFB_XMM BSWAP IN1 + pxor IN1, DATA + call __clmul_gf128mul_ble + sub $16, %rdx + add $16, %rsi + cmp $16, %rdx + jge .Lupdate_loop + PSHUFB_XMM BSWAP DATA + movups DATA, (%rdi) +.Lupdate_just_ret: + ret + +/* + * void clmul_ghash_setkey(be128 *shash, const u8 *key); + * + * Calculate hash_key << 1 mod poly + */ +ENTRY(clmul_ghash_setkey) + movaps .Lbswap_mask, BSWAP + movups (%rsi), %xmm0 + PSHUFB_XMM BSWAP %xmm0 + movaps %xmm0, %xmm1 + psllq $1, %xmm0 + psrlq $63, %xmm1 + movaps %xmm1, %xmm2 + pslldq $8, %xmm1 + psrldq $8, %xmm2 + por %xmm1, %xmm0 + # reduction + pshufd $0b00100100, %xmm2, %xmm1 + pcmpeqd .Ltwo_one, %xmm1 + pand .Lpoly, %xmm1 + pxor %xmm1, %xmm0 + movups %xmm0, (%rdi) + ret diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c new file mode 100644 index 000000000000..cbcc8d8ea93a --- /dev/null +++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c @@ -0,0 +1,333 @@ +/* + * Accelerated GHASH implementation with Intel PCLMULQDQ-NI + * instructions. This file contains glue code. + * + * Copyright (c) 2009 Intel Corp. + * Author: Huang Ying <ying.huang@intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/crypto.h> +#include <crypto/algapi.h> +#include <crypto/cryptd.h> +#include <crypto/gf128mul.h> +#include <crypto/internal/hash.h> +#include <asm/i387.h> + +#define GHASH_BLOCK_SIZE 16 +#define GHASH_DIGEST_SIZE 16 + +void clmul_ghash_mul(char *dst, const be128 *shash); + +void clmul_ghash_update(char *dst, const char *src, unsigned int srclen, + const be128 *shash); + +void clmul_ghash_setkey(be128 *shash, const u8 *key); + +struct ghash_async_ctx { + struct cryptd_ahash *cryptd_tfm; +}; + +struct ghash_ctx { + be128 shash; +}; + +struct ghash_desc_ctx { + u8 buffer[GHASH_BLOCK_SIZE]; + u32 bytes; +}; + +static int ghash_init(struct shash_desc *desc) +{ + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); + + memset(dctx, 0, sizeof(*dctx)); + + return 0; +} + +static int ghash_setkey(struct crypto_shash *tfm, + const u8 *key, unsigned int keylen) +{ + struct ghash_ctx *ctx = crypto_shash_ctx(tfm); + + if (keylen != GHASH_BLOCK_SIZE) { + crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + clmul_ghash_setkey(&ctx->shash, key); + + return 0; +} + +static int ghash_update(struct shash_desc *desc, + const u8 *src, unsigned int srclen) +{ + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); + struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + u8 *dst = dctx->buffer; + + kernel_fpu_begin(); + if (dctx->bytes) { + int n = min(srclen, dctx->bytes); + u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes); + + dctx->bytes -= n; + srclen -= n; + + while (n--) + *pos++ ^= *src++; + + if (!dctx->bytes) + clmul_ghash_mul(dst, &ctx->shash); + } + + clmul_ghash_update(dst, src, srclen, &ctx->shash); + kernel_fpu_end(); + + if (srclen & 0xf) { + src += srclen - (srclen & 0xf); + srclen &= 0xf; + dctx->bytes = GHASH_BLOCK_SIZE - srclen; + while (srclen--) + *dst++ ^= *src++; + } + + return 0; +} + +static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) +{ + u8 *dst = dctx->buffer; + + if (dctx->bytes) { + u8 *tmp = dst + (GHASH_BLOCK_SIZE - dctx->bytes); + + while (dctx->bytes--) + *tmp++ ^= 0; + + kernel_fpu_begin(); + clmul_ghash_mul(dst, &ctx->shash); + kernel_fpu_end(); + } + + dctx->bytes = 0; +} + +static int ghash_final(struct shash_desc *desc, u8 *dst) +{ + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); + struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + u8 *buf = dctx->buffer; + + ghash_flush(ctx, dctx); + memcpy(dst, buf, GHASH_BLOCK_SIZE); + + return 0; +} + +static struct shash_alg ghash_alg = { + .digestsize = GHASH_DIGEST_SIZE, + .init = ghash_init, + .update = ghash_update, + .final = ghash_final, + .setkey = ghash_setkey, + .descsize = sizeof(struct ghash_desc_ctx), + .base = { + .cra_name = "__ghash", + .cra_driver_name = "__ghash-pclmulqdqni", + .cra_priority = 0, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = GHASH_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct ghash_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(ghash_alg.base.cra_list), + }, +}; + +static int ghash_async_init(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm); + struct ahash_request *cryptd_req = ahash_request_ctx(req); + struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm; + + if (!irq_fpu_usable()) { + memcpy(cryptd_req, req, sizeof(*req)); + ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base); + return crypto_ahash_init(cryptd_req); + } else { + struct shash_desc *desc = cryptd_shash_desc(cryptd_req); + struct crypto_shash *child = cryptd_ahash_child(cryptd_tfm); + + desc->tfm = child; + desc->flags = req->base.flags; + return crypto_shash_init(desc); + } +} + +static int ghash_async_update(struct ahash_request *req) +{ + struct ahash_request *cryptd_req = ahash_request_ctx(req); + + if (!irq_fpu_usable()) { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm); + struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm; + + memcpy(cryptd_req, req, sizeof(*req)); + ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base); + return crypto_ahash_update(cryptd_req); + } else { + struct shash_desc *desc = cryptd_shash_desc(cryptd_req); + return shash_ahash_update(req, desc); + } +} + +static int ghash_async_final(struct ahash_request *req) +{ + struct ahash_request *cryptd_req = ahash_request_ctx(req); + + if (!irq_fpu_usable()) { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm); + struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm; + + memcpy(cryptd_req, req, sizeof(*req)); + ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base); + return crypto_ahash_final(cryptd_req); + } else { + struct shash_desc *desc = cryptd_shash_desc(cryptd_req); + return crypto_shash_final(desc, req->result); + } +} + +static int ghash_async_digest(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm); + struct ahash_request *cryptd_req = ahash_request_ctx(req); + struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm; + + if (!irq_fpu_usable()) { + memcpy(cryptd_req, req, sizeof(*req)); + ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base); + return crypto_ahash_digest(cryptd_req); + } else { + struct shash_desc *desc = cryptd_shash_desc(cryptd_req); + struct crypto_shash *child = cryptd_ahash_child(cryptd_tfm); + + desc->tfm = child; + desc->flags = req->base.flags; + return shash_ahash_digest(req, desc); + } +} + +static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen) +{ + struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm); + struct crypto_ahash *child = &ctx->cryptd_tfm->base; + int err; + + crypto_ahash_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_ahash_set_flags(child, crypto_ahash_get_flags(tfm) + & CRYPTO_TFM_REQ_MASK); + err = crypto_ahash_setkey(child, key, keylen); + crypto_ahash_set_flags(tfm, crypto_ahash_get_flags(child) + & CRYPTO_TFM_RES_MASK); + + return 0; +} + +static int ghash_async_init_tfm(struct crypto_tfm *tfm) +{ + struct cryptd_ahash *cryptd_tfm; + struct ghash_async_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_tfm = cryptd_alloc_ahash("__ghash-pclmulqdqni", 0, 0); + if (IS_ERR(cryptd_tfm)) + return PTR_ERR(cryptd_tfm); + ctx->cryptd_tfm = cryptd_tfm; + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct ahash_request) + + crypto_ahash_reqsize(&cryptd_tfm->base)); + + return 0; +} + +static void ghash_async_exit_tfm(struct crypto_tfm *tfm) +{ + struct ghash_async_ctx *ctx = crypto_tfm_ctx(tfm); + + cryptd_free_ahash(ctx->cryptd_tfm); +} + +static struct ahash_alg ghash_async_alg = { + .init = ghash_async_init, + .update = ghash_async_update, + .final = ghash_async_final, + .setkey = ghash_async_setkey, + .digest = ghash_async_digest, + .halg = { + .digestsize = GHASH_DIGEST_SIZE, + .base = { + .cra_name = "ghash", + .cra_driver_name = "ghash-clmulni", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC, + .cra_blocksize = GHASH_BLOCK_SIZE, + .cra_type = &crypto_ahash_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(ghash_async_alg.halg.base.cra_list), + .cra_init = ghash_async_init_tfm, + .cra_exit = ghash_async_exit_tfm, + }, + }, +}; + +static int __init ghash_pclmulqdqni_mod_init(void) +{ + int err; + + if (!cpu_has_pclmulqdq) { + printk(KERN_INFO "Intel PCLMULQDQ-NI instructions are not" + " detected.\n"); + return -ENODEV; + } + + err = crypto_register_shash(&ghash_alg); + if (err) + goto err_out; + err = crypto_register_ahash(&ghash_async_alg); + if (err) + goto err_shash; + + return 0; + +err_shash: + crypto_unregister_shash(&ghash_alg); +err_out: + return err; +} + +static void __exit ghash_pclmulqdqni_mod_exit(void) +{ + crypto_unregister_ahash(&ghash_async_alg); + crypto_unregister_shash(&ghash_alg); +} + +module_init(ghash_pclmulqdqni_mod_init); +module_exit(ghash_pclmulqdqni_mod_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GHASH Message Digest Algorithm, " + "acclerated by PCLMULQDQ-NI"); +MODULE_ALIAS("ghash"); diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 9cfc88b97742..613700f27a4a 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -248,6 +248,7 @@ extern const char * const x86_power_flags[32]; #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) +#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) # define cpu_has_invlpg 1 diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 1c22cb05ad6a..5d89fd2a3690 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -65,11 +65,12 @@ /* hpet memory map physical address */ extern unsigned long hpet_address; extern unsigned long force_hpet_address; +extern u8 hpet_blockid; extern int hpet_force_user; extern int is_hpet_enabled(void); extern int hpet_enable(void); extern void hpet_disable(void); -extern unsigned long hpet_readl(unsigned long a); +extern unsigned int hpet_readl(unsigned int a); extern void force_hpet_resume(void); extern void hpet_msi_unmask(unsigned int irq); @@ -78,9 +79,9 @@ extern void hpet_msi_write(unsigned int irq, struct msi_msg *msg); extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg); #ifdef CONFIG_PCI_MSI -extern int arch_setup_hpet_msi(unsigned int irq); +extern int arch_setup_hpet_msi(unsigned int irq, unsigned int id); #else -static inline int arch_setup_hpet_msi(unsigned int irq) +static inline int arch_setup_hpet_msi(unsigned int irq, unsigned int id) { return -EINVAL; } diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 0b20bbb758f2..ebfb8a9e11f7 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h @@ -10,6 +10,8 @@ #ifndef _ASM_X86_I387_H #define _ASM_X86_I387_H +#ifndef __ASSEMBLY__ + #include <linux/sched.h> #include <linux/kernel_stat.h> #include <linux/regset.h> @@ -411,4 +413,9 @@ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) } } +#endif /* __ASSEMBLY__ */ + +#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5 +#define PSHUFB_XMM5_XMM6 .byte 0x66, 0x0f, 0x38, 0x00, 0xf5 + #endif /* _ASM_X86_I387_H */ diff --git a/arch/x86/include/asm/inst.h b/arch/x86/include/asm/inst.h new file mode 100644 index 000000000000..14cf526091f9 --- /dev/null +++ b/arch/x86/include/asm/inst.h @@ -0,0 +1,150 @@ +/* + * Generate .byte code for some instructions not supported by old + * binutils. + */ +#ifndef X86_ASM_INST_H +#define X86_ASM_INST_H + +#ifdef __ASSEMBLY__ + + .macro XMM_NUM opd xmm + .ifc \xmm,%xmm0 + \opd = 0 + .endif + .ifc \xmm,%xmm1 + \opd = 1 + .endif + .ifc \xmm,%xmm2 + \opd = 2 + .endif + .ifc \xmm,%xmm3 + \opd = 3 + .endif + .ifc \xmm,%xmm4 + \opd = 4 + .endif + .ifc \xmm,%xmm5 + \opd = 5 + .endif + .ifc \xmm,%xmm6 + \opd = 6 + .endif + .ifc \xmm,%xmm7 + \opd = 7 + .endif + .ifc \xmm,%xmm8 + \opd = 8 + .endif + .ifc \xmm,%xmm9 + \opd = 9 + .endif + .ifc \xmm,%xmm10 + \opd = 10 + .endif + .ifc \xmm,%xmm11 + \opd = 11 + .endif + .ifc \xmm,%xmm12 + \opd = 12 + .endif + .ifc \xmm,%xmm13 + \opd = 13 + .endif + .ifc \xmm,%xmm14 + \opd = 14 + .endif + .ifc \xmm,%xmm15 + \opd = 15 + .endif + .endm + + .macro PFX_OPD_SIZE + .byte 0x66 + .endm + + .macro PFX_REX opd1 opd2 + .if (\opd1 | \opd2) & 8 + .byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) + .endif + .endm + + .macro MODRM mod opd1 opd2 + .byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3) + .endm + + .macro PSHUFB_XMM xmm1 xmm2 + XMM_NUM pshufb_opd1 \xmm1 + XMM_NUM pshufb_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX pshufb_opd1 pshufb_opd2 + .byte 0x0f, 0x38, 0x00 + MODRM 0xc0 pshufb_opd1 pshufb_opd2 + .endm + + .macro PCLMULQDQ imm8 xmm1 xmm2 + XMM_NUM clmul_opd1 \xmm1 + XMM_NUM clmul_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX clmul_opd1 clmul_opd2 + .byte 0x0f, 0x3a, 0x44 + MODRM 0xc0 clmul_opd1 clmul_opd2 + .byte \imm8 + .endm + + .macro AESKEYGENASSIST rcon xmm1 xmm2 + XMM_NUM aeskeygen_opd1 \xmm1 + XMM_NUM aeskeygen_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX aeskeygen_opd1 aeskeygen_opd2 + .byte 0x0f, 0x3a, 0xdf + MODRM 0xc0 aeskeygen_opd1 aeskeygen_opd2 + .byte \rcon + .endm + + .macro AESIMC xmm1 xmm2 + XMM_NUM aesimc_opd1 \xmm1 + XMM_NUM aesimc_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX aesimc_opd1 aesimc_opd2 + .byte 0x0f, 0x38, 0xdb + MODRM 0xc0 aesimc_opd1 aesimc_opd2 + .endm + + .macro AESENC xmm1 xmm2 + XMM_NUM aesenc_opd1 \xmm1 + XMM_NUM aesenc_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX aesenc_opd1 aesenc_opd2 + .byte 0x0f, 0x38, 0xdc + MODRM 0xc0 aesenc_opd1 aesenc_opd2 + .endm + + .macro AESENCLAST xmm1 xmm2 + XMM_NUM aesenclast_opd1 \xmm1 + XMM_NUM aesenclast_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX aesenclast_opd1 aesenclast_opd2 + .byte 0x0f, 0x38, 0xdd + MODRM 0xc0 aesenclast_opd1 aesenclast_opd2 + .endm + + .macro AESDEC xmm1 xmm2 + XMM_NUM aesdec_opd1 \xmm1 + XMM_NUM aesdec_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX aesdec_opd1 aesdec_opd2 + .byte 0x0f, 0x38, 0xde + MODRM 0xc0 aesdec_opd1 aesdec_opd2 + .endm + + .macro AESDECLAST xmm1 xmm2 + XMM_NUM aesdeclast_opd1 \xmm1 + XMM_NUM aesdeclast_opd2 \xmm2 + PFX_OPD_SIZE + PFX_REX aesdeclast_opd1 aesdeclast_opd2 + .byte 0x0f, 0x38, 0xdf + MODRM 0xc0 aesdeclast_opd1 aesdeclast_opd2 + .endm +#endif + +#endif diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 67e929b89875..87eee07da21f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -624,6 +624,7 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table) } hpet_address = hpet_tbl->address.address; + hpet_blockid = hpet_tbl->sequence; /* * Some broken BIOSes advertise HPET at 0x0. We really do not diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index ad8c75b9e453..efb2b9cd132c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -647,7 +647,7 @@ static int __init calibrate_APIC_clock(void) calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta); - apic_printk(APIC_VERBOSE, "..... mult: %ld\n", lapic_clockevent.mult); + apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult); apic_printk(APIC_VERBOSE, "..... calibration result: %u\n", calibration_result); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c0b4468683f9..d5d498fbee4b 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3267,7 +3267,8 @@ void destroy_irq(unsigned int irq) * MSI message composition */ #ifdef CONFIG_PCI_MSI -static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) +static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, + struct msi_msg *msg, u8 hpet_id) { struct irq_cfg *cfg; int err; @@ -3301,7 +3302,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms irte.dest_id = IRTE_DEST(dest); /* Set source-id of interrupt request */ - set_msi_sid(&irte, pdev); + if (pdev) + set_msi_sid(&irte, pdev); + else + set_hpet_sid(&irte, hpet_id); modify_irte(irq, &irte); @@ -3466,7 +3470,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) int ret; struct msi_msg msg; - ret = msi_compose_msg(dev, irq, &msg); + ret = msi_compose_msg(dev, irq, &msg, -1); if (ret < 0) return ret; @@ -3599,7 +3603,7 @@ int arch_setup_dmar_msi(unsigned int irq) int ret; struct msi_msg msg; - ret = msi_compose_msg(NULL, irq, &msg); + ret = msi_compose_msg(NULL, irq, &msg, -1); if (ret < 0) return ret; dmar_msi_write(irq, &msg); @@ -3639,6 +3643,19 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) #endif /* CONFIG_SMP */ +static struct irq_chip ir_hpet_msi_type = { + .name = "IR-HPET_MSI", + .unmask = hpet_msi_unmask, + .mask = hpet_msi_mask, +#ifdef CONFIG_INTR_REMAP + .ack = ir_ack_apic_edge, +#ifdef CONFIG_SMP + .set_affinity = ir_set_msi_irq_affinity, +#endif +#endif + .retrigger = ioapic_retrigger_irq, +}; + static struct irq_chip hpet_msi_type = { .name = "HPET_MSI", .unmask = hpet_msi_unmask, @@ -3650,20 +3667,36 @@ static struct irq_chip hpet_msi_type = { .retrigger = ioapic_retrigger_irq, }; -int arch_setup_hpet_msi(unsigned int irq) +int arch_setup_hpet_msi(unsigned int irq, unsigned int id) { int ret; struct msi_msg msg; struct irq_desc *desc = irq_to_desc(irq); - ret = msi_compose_msg(NULL, irq, &msg); + if (intr_remapping_enabled) { + struct intel_iommu *iommu = map_hpet_to_ir(id); + int index; + + if (!iommu) + return -1; + + index = alloc_irte(iommu, irq, 1); + if (index < 0) + return -1; + } + + ret = msi_compose_msg(NULL, irq, &msg, id); if (ret < 0) return ret; hpet_msi_write(irq, &msg); desc->status |= IRQ_MOVE_PCNTXT; - set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq, - "edge"); + if (irq_remapped(irq)) + set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type, + handle_edge_irq, "edge"); + else + set_irq_chip_and_handler_name(irq, &hpet_msi_type, + handle_edge_irq, "edge"); return 0; } diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index dedc2bddf7a5..ba6e65884603 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -33,6 +33,7 @@ * HPET address is set in acpi/boot.c, when an ACPI entry exists */ unsigned long hpet_address; +u8 hpet_blockid; /* OS timer block num */ #ifdef CONFIG_PCI_MSI static unsigned long hpet_num_timers; #endif @@ -47,12 +48,12 @@ struct hpet_dev { char name[10]; }; -unsigned long hpet_readl(unsigned long a) +inline unsigned int hpet_readl(unsigned int a) { return readl(hpet_virt_address + a); } -static inline void hpet_writel(unsigned long d, unsigned long a) +static inline void hpet_writel(unsigned int d, unsigned int a) { writel(d, hpet_virt_address + a); } @@ -167,7 +168,7 @@ do { \ static void hpet_reserve_msi_timers(struct hpet_data *hd); -static void hpet_reserve_platform_timers(unsigned long id) +static void hpet_reserve_platform_timers(unsigned int id) { struct hpet __iomem *hpet = hpet_virt_address; struct hpet_timer __iomem *timer = &hpet->hpet_timers[2]; @@ -205,7 +206,7 @@ static void hpet_reserve_platform_timers(unsigned long id) } #else -static void hpet_reserve_platform_timers(unsigned long id) { } +static void hpet_reserve_platform_timers(unsigned int id) { } #endif /* @@ -246,7 +247,7 @@ static void hpet_reset_counter(void) static void hpet_start_counter(void) { - unsigned long cfg = hpet_readl(HPET_CFG); + unsigned int cfg = hpet_readl(HPET_CFG); cfg |= HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); } @@ -271,7 +272,7 @@ static void hpet_resume_counter(void) static void hpet_enable_legacy_int(void) { - unsigned long cfg = hpet_readl(HPET_CFG); + unsigned int cfg = hpet_readl(HPET_CFG); cfg |= HPET_CFG_LEGACY; hpet_writel(cfg, HPET_CFG); @@ -314,7 +315,7 @@ static int hpet_setup_msi_irq(unsigned int irq); static void hpet_set_mode(enum clock_event_mode mode, struct clock_event_device *evt, int timer) { - unsigned long cfg, cmp, now; + unsigned int cfg, cmp, now; uint64_t delta; switch (mode) { @@ -323,7 +324,7 @@ static void hpet_set_mode(enum clock_event_mode mode, delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult; delta >>= evt->shift; now = hpet_readl(HPET_COUNTER); - cmp = now + (unsigned long) delta; + cmp = now + (unsigned int) delta; cfg = hpet_readl(HPET_Tn_CFG(timer)); /* Make sure we use edge triggered interrupts */ cfg &= ~HPET_TN_LEVEL; @@ -339,7 +340,7 @@ static void hpet_set_mode(enum clock_event_mode mode, * (See AMD-8111 HyperTransport I/O Hub Data Sheet, * Publication # 24674) */ - hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); + hpet_writel((unsigned int) delta, HPET_Tn_CMP(timer)); hpet_start_counter(); hpet_print_config(); break; @@ -383,13 +384,24 @@ static int hpet_next_event(unsigned long delta, hpet_writel(cnt, HPET_Tn_CMP(timer)); /* - * We need to read back the CMP register to make sure that - * what we wrote hit the chip before we compare it to the - * counter. + * We need to read back the CMP register on certain HPET + * implementations (ATI chipsets) which seem to delay the + * transfer of the compare register into the internal compare + * logic. With small deltas this might actually be too late as + * the counter could already be higher than the compare value + * at that point and we would wait for the next hpet interrupt + * forever. We found out that reading the CMP register back + * forces the transfer so we can rely on the comparison with + * the counter register below. If the read back from the + * compare register does not match the value we programmed + * then we might have a real hardware problem. We can not do + * much about it here, but at least alert the user/admin with + * a prominent warning. */ - WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt); + WARN_ONCE(hpet_readl(HPET_Tn_CMP(timer)) != cnt, + KERN_WARNING "hpet: compare register read back failed.\n"); - return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; + return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; } static void hpet_legacy_set_mode(enum clock_event_mode mode, @@ -415,7 +427,7 @@ static struct hpet_dev *hpet_devs; void hpet_msi_unmask(unsigned int irq) { struct hpet_dev *hdev = get_irq_data(irq); - unsigned long cfg; + unsigned int cfg; /* unmask it */ cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); @@ -425,7 +437,7 @@ void hpet_msi_unmask(unsigned int irq) void hpet_msi_mask(unsigned int irq) { - unsigned long cfg; + unsigned int cfg; struct hpet_dev *hdev = get_irq_data(irq); /* mask it */ @@ -467,7 +479,7 @@ static int hpet_msi_next_event(unsigned long delta, static int hpet_setup_msi_irq(unsigned int irq) { - if (arch_setup_hpet_msi(irq)) { + if (arch_setup_hpet_msi(irq, hpet_blockid)) { destroy_irq(irq); return -EINVAL; } @@ -584,6 +596,8 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) unsigned int num_timers_used = 0; int i; + if (boot_cpu_has(X86_FEATURE_ARAT)) + return; id = hpet_readl(HPET_ID); num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); @@ -598,7 +612,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) { struct hpet_dev *hdev = &hpet_devs[num_timers_used]; - unsigned long cfg = hpet_readl(HPET_Tn_CFG(i)); + unsigned int cfg = hpet_readl(HPET_Tn_CFG(i)); /* Only consider HPET timer with MSI support */ if (!(cfg & HPET_TN_FSB_CAP)) @@ -813,7 +827,7 @@ static int hpet_clocksource_register(void) */ int __init hpet_enable(void) { - unsigned long id; + unsigned int id; int i; if (!is_hpet_capable()) @@ -872,10 +886,8 @@ int __init hpet_enable(void) if (id & HPET_ID_LEGSUP) { hpet_legacy_clockevent_register(); - hpet_msi_capability_lookup(2); return 1; } - hpet_msi_capability_lookup(0); return 0; out_nohpet: @@ -908,9 +920,17 @@ static __init int hpet_late_init(void) if (!hpet_virt_address) return -ENODEV; + if (hpet_readl(HPET_ID) & HPET_ID_LEGSUP) + hpet_msi_capability_lookup(2); + else + hpet_msi_capability_lookup(0); + hpet_reserve_platform_timers(hpet_readl(HPET_ID)); hpet_print_config(); + if (boot_cpu_has(X86_FEATURE_ARAT)) + return 0; + for_each_online_cpu(cpu) { hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu); } @@ -925,7 +945,7 @@ fs_initcall(hpet_late_init); void hpet_disable(void) { if (is_hpet_capable()) { - unsigned long cfg = hpet_readl(HPET_CFG); + unsigned int cfg = hpet_readl(HPET_CFG); if (hpet_legacy_int_enabled) { cfg &= ~HPET_CFG_LEGACY; @@ -965,8 +985,8 @@ static int hpet_prev_update_sec; static struct rtc_time hpet_alarm_time; static unsigned long hpet_pie_count; static u32 hpet_t1_cmp; -static unsigned long hpet_default_delta; -static unsigned long hpet_pie_delta; +static u32 hpet_default_delta; +static u32 hpet_pie_delta; static unsigned long hpet_pie_limit; static rtc_irq_handler irq_handler; @@ -1017,7 +1037,8 @@ EXPORT_SYMBOL_GPL(hpet_unregister_irq_handler); */ int hpet_rtc_timer_init(void) { - unsigned long cfg, cnt, delta, flags; + unsigned int cfg, cnt, delta; + unsigned long flags; if (!is_hpet_enabled()) return 0; @@ -1027,7 +1048,7 @@ int hpet_rtc_timer_init(void) clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC; clc >>= hpet_clockevent.shift + DEFAULT_RTC_SHIFT; - hpet_default_delta = (unsigned long) clc; + hpet_default_delta = clc; } if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit) @@ -1113,7 +1134,7 @@ int hpet_set_periodic_freq(unsigned long freq) clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC; do_div(clc, freq); clc >>= hpet_clockevent.shift; - hpet_pie_delta = (unsigned long) clc; + hpet_pie_delta = clc; } return 1; } @@ -1127,7 +1148,7 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq); static void hpet_rtc_timer_reinit(void) { - unsigned long cfg, delta; + unsigned int cfg, delta; int lost_ints = -1; if (unlikely(!hpet_rtc_flags)) { diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c index 611b9e2360d3..74c92bb194df 100644 --- a/arch/x86/kernel/vmiclock_32.c +++ b/arch/x86/kernel/vmiclock_32.c @@ -226,7 +226,7 @@ static void __devinit vmi_time_init_clockevent(void) evt->min_delta_ns = clockevent_delta2ns(1, evt); evt->cpumask = cpumask_of(cpu); - printk(KERN_WARNING "vmi: registering clock event %s. mult=%lu shift=%u\n", + printk(KERN_WARNING "vmi: registering clock event %s. mult=%u shift=%u\n", evt->name, evt->mult, evt->shift); clockevents_register_device(evt); } diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index e02d92d12bcd..9055e5872ff0 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -73,7 +73,8 @@ void update_vsyscall_tz(void) write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); } -void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, + u32 mult) { unsigned long flags; @@ -82,7 +83,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) vsyscall_gtod_data.clock.vread = clock->vread; vsyscall_gtod_data.clock.cycle_last = clock->cycle_last; vsyscall_gtod_data.clock.mask = clock->mask; - vsyscall_gtod_data.clock.mult = clock->mult; + vsyscall_gtod_data.clock.mult = mult; vsyscall_gtod_data.clock.shift = clock->shift; vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; |