diff options
Diffstat (limited to 'arch/arm')
200 files changed, 14135 insertions, 3299 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f9da419..942fad9 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -691,9 +691,9 @@ proc_types: .word 0x41069260 @ ARM926EJ-S (v5TEJ) .word 0xff0ffff0 - b __arm926ejs_mmu_cache_on - b __armv4_mmu_cache_off - b __armv5tej_mmu_cache_flush + W(b) __arm926ejs_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv5tej_mmu_cache_flush .word 0x00007000 @ ARM7 IDs .word 0x0000f000 diff --git a/arch/arm/configs/android_4430_defconfig b/arch/arm/configs/android_4430_defconfig new file mode 100644 index 0000000..d432abe --- /dev/null +++ b/arch/arm/configs/android_4430_defconfig @@ -0,0 +1,1926 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.35 +# Fri Sep 3 08:14:37 2010 +# +CONFIG_ARM=y +CONFIG_HAVE_PWM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# 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_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_PANIC_TIMEOUT=0 +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_ASHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +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_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=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 +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 is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# 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_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX 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_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_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 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_NUC93X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P6440 is not set +# CONFIG_ARCH_S5P6442 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_PLAT_SPEAR is not set + +# +# TI OMAP Implementations +# +# CONFIG_ARCH_OMAP1 is not set +CONFIG_ARCH_OMAP2PLUS=y +# CONFIG_ARCH_OMAP2 is not set +# CONFIG_ARCH_OMAP3 is not set +CONFIG_ARCH_OMAP4=y + +# +# OMAP Feature Selections +# +CONFIG_OMAP_SMARTREFLEX=y +# CONFIG_OMAP_SMARTREFLEX_TESTING is not set +CONFIG_OMAP_SMARTREFLEX_CLASS3=y +# CONFIG_OMAP_RESET_CLOCKS is not set +# CONFIG_OMAP_MUX is not set +CONFIG_OMAP_MCBSP=y +CONFIG_OMAP_MBOX_FWK=y +CONFIG_OMAP_REMOTE_PROC=y +CONFIG_OMAP_RPROC_MEMPOOL_SIZE=0x600000 +CONFIG_OMAP_IOMMU=y +# CONFIG_OMAP_IOMMU_DEBUG is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y +# CONFIG_OMAP_PM is not set + +# +# OMAP Board Type +# +# CONFIG_WIFI_CONTROL_FUNC is not set +# CONFIG_TIWLAN_SDIO is not set +# CONFIG_OMAP4_ES1 is not set +CONFIG_MACH_OMAP_4430SDP=y +CONFIG_MACH_OMAP4_PANDA=y +# CONFIG_ERRATA_OMAP4_AXI2OCP is not set + +# +# Processor Type +# +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_PL310_ERRATA_588369 is not set +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_GIC=y +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_SMP=y +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCAL_TIMERS=y +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_HZ=128 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=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=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS2,115200n8 initrd=0x81600000,20M ramdisk_size=20480" +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND_NVS=y +CONFIG_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_SUSPEND_FREEZER=y +CONFIG_HAS_WAKELOCK=y +CONFIG_HAS_EARLYSUSPEND=y +CONFIG_WAKELOCK=y +CONFIG_WAKELOCK_STAT=y +CONFIG_USER_WAKELOCK=y +CONFIG_EARLYSUSPEND=y +# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set +CONFIG_CONSOLE_EARLYSUSPEND=y +# CONFIG_FB_EARLYSUSPEND is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_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=y +CONFIG_IP_PNP_RARP=y +# 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 is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NET_ACTIVITY_STATS=y +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_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_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_RPS=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_L2CAP=y +# CONFIG_BT_L2CAP_EXT_FEATURES is not set +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +# CONFIG_BT_BNEP is not set +# CONFIG_BT_HIDP is not set + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_PM is not set +# CONFIG_RFKILL_INPUT is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# 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=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# 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_AD525X_DPOT is not set +CONFIG_ANDROID_PMEM=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_KERNEL_DEBUGGER_CORE=y +# CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set +CONFIG_SENSORS_BH1780=y +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +CONFIG_UID_STAT=y +CONFIG_BMP085=y +# CONFIG_WL127X_RFKILL is not set +# CONFIG_APANIC is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 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_KS8842 is not set +CONFIG_KS8851=y +# CONFIG_KS8851_MLL is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN 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 is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_KEYRESET=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# 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_OMAP4=y +# CONFIG_KEYBOARD_TWL4030 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879_I2C is not set +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE 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 +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +CONFIG_TOUCHSCREEN_SYNTM12XX=y +# CONFIG_TOUCHSCREEN_TPS6507X is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +CONFIG_INPUT_KEYCHORD=y +# 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_TWL4030_PWRBUTTON is not set +# CONFIG_INPUT_TWL4030_VIBRA is not set +# CONFIG_INPUT_TWL6040_VIBRA is not set +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +CONFIG_INPUT_SFH7741=y +CONFIG_INPUT_CMA3000_I2C=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# 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_DCC_TTY is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=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_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX 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_STUB 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_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_OMAP24XX=y +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS 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: +# +# CONFIG_GPIO_IT8761E is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_TWL4030 is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2782 is not set +CONFIG_TWL6030_BCI_BATTERY=y +CONFIG_CHARGER_BQ2415x=y +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 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_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +CONFIG_SENSORS_LM75=y +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 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 +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=y +# CONFIG_TWL4030_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_MFD_SUPPORT=y +CONFIG_MFD_CORE=y +# CONFIG_MFD_88PM860X 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_HTC_I2CPLD is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_POWER is not set +# CONFIG_TWL4030_CODEC is not set +# CONFIG_MFD_TC35892 is not set +CONFIG_TWL6030_PWM=y +CONFIG_TWL6030_GPADC=y +CONFIG_TWL6040_CODEC=y +# 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_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13783 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_AB8500_CORE is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY 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_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +CONFIG_REGULATOR_TWL4030=y +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_VIDEO_ALLOW_V4L1 is not set +CONFIG_VIDEO_V4L1_COMPAT=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +CONFIG_IR_CORE=y +CONFIG_VIDEO_IR=y +CONFIG_RC_MAP=y +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +# CONFIG_IR_IMON is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF_DMA_CONTIG=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_IR_I2C=y +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_OMAP2_VOUT=y +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_I2C_SI4713 is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_DAB is not set +CONFIG_DMM_OMAP=y +CONFIG_TILER_OMAP=y + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL 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_TMIO is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=4 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set +CONFIG_OMAP2_DSS_DPI=y +# CONFIG_OMAP2_DSS_RFBI is not set +# CONFIG_OMAP2_DSS_VENC is not set +CONFIG_OMAP2_DSS_HDMI=y +CONFIG_OMAP2_DSS_DSI=y +# CONFIG_OMAP2_DSS_USE_DSI_PLL is not set +CONFIG_OMAP2_DSS_FAKE_VSYNC=y +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +CONFIG_FB_OMAP2_NUM_FBS=2 + +# +# OMAP2/3 Display Device Drivers +# +# CONFIG_PANEL_GENERIC is not set +# CONFIG_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_PANEL_SHARP_LQ043T1DG01 is not set +CONFIG_PANEL_PICO_DLP=y +CONFIG_PANEL_TAAL=y +# CONFIG_PANEL_TOPPOLY_TDO35S is not set +# CONFIG_PANEL_TPO_TD043MTEA1 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_ADP8860 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_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +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=y +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 +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_ABE_DSP=y +CONFIG_SND_OMAP_SOC_MCBSP=y +CONFIG_SND_OMAP_SOC_MCPDM=y +CONFIG_SND_OMAP_SOC_ABE=y +CONFIG_SND_OMAP_SOC_DMIC=y +CONFIG_SND_OMAP_SOC_SDP4430=y +CONFIG_SND_OMAP_SOC_HDMI=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_DMIC=y +CONFIG_SND_SOC_TWL6040=y +# CONFIG_SOUND_PRIME is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 44xx high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +CONFIG_USB_MUSB_PERIPHERAL=y +# CONFIG_USB_MUSB_OTG is not set +CONFIG_USB_GADGET_MUSB_HDRC=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# 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_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 +# CONFIG_USB_GADGET_S3C2410 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_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +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 is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_ANDROID is not set +CONFIG_USB_CDC_COMPOSITE=m +# CONFIG_USB_G_NOKIA is not set +CONFIG_USB_G_MULTI=m +CONFIG_USB_G_MULTI_RNDIS=y +CONFIG_USB_G_MULTI_CDC=y +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_TWL4030_USB is not set +CONFIG_NOP_USB_XCEIV=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_EMBEDDED_SDIO is not set +# CONFIG_MMC_PARANOID_SD_INIT is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +CONFIG_MMC_OMAP_HS=y +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +CONFIG_LEDS_PWM=y +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TRIGGERS is not set +CONFIG_SWITCH=y +CONFIG_SWITCH_GPIO=y +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_ALARM=y +CONFIG_RTC_INTF_ALARM_DEV=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +# CONFIG_ECHO is not set +# CONFIG_COMEDI is not set + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_RAM_CONSOLE=y +CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y +# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set +# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set +CONFIG_ANDROID_TIMED_OUTPUT=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +# CONFIG_POHMELFS is not set + +# +# RAR Register Driver +# +CONFIG_IIO=y +# CONFIG_IIO_RING_BUFFER is not set +# CONFIG_IIO_TRIGGER is not set + +# +# Accelerometers +# +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set + +# +# Analog to digital convertors +# +# CONFIG_MAX1363 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16260 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16300 is not set +# CONFIG_ADIS16350 is not set +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_TSL2563 is not set + +# +# Magnetometer sensors +# +CONFIG_SENSORS_HMC5843=y + +# +# Triggers - standalone +# +# CONFIG_RAMZSWAP is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_FB_SM7XX is not set + +# +# Texas Instruments shared transport line discipline +# +CONFIG_TI_ST=m +CONFIG_ST_BT=m +CONFIG_ST_FM=m +# CONFIG_ADIS16255 is not set +CONFIG_Sys_Link=y +CONFIG_SYSLINK_PROC=y +CONFIG_SYSLINK_PROC4430=y +CONFIG_DUCATI_BASEIMAGE_PHYS_ADDR=0x9CF00000 +CONFIG_SYSLINK_DUCATI_PM=y +CONFIG_OMAP_DEVICE_HANDLER=y +CONFIG_MPU_SYSLINK_PLATFORM=y +CONFIG_MPU_SYSLINK_IPC=y +CONFIG_SYSLINK_USE_SYSMGR=y +CONFIG_SYSLINK_IOMMU_ENABLE=y +CONFIG_SYSLINK_RECOVERY=y + +# +# 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 is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS 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 +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_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_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL 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 is not set +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 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_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 is not set +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# 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_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_LKDTM is not set +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +# CONFIG_FAULT_INJECTION 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 +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# 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=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# 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=y +# 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=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +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/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 889922a..67b5abb6 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -157,7 +157,7 @@ CONFIG_LEDS_GPIO=m CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_XFS_FS=m diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig index 316af54..9c0ad79 100644 --- a/arch/arm/configs/netx_defconfig +++ b/arch/arm/configs/netx_defconfig @@ -60,7 +60,7 @@ CONFIG_FB_ARMCLCD=y # CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_INOTIFY=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index d5f00d7..5708151 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -8,7 +8,6 @@ CONFIG_LOG_BUF_SHIFT=16 CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_OPROFILE=y @@ -21,6 +20,8 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_OMAP=y +CONFIG_OMAP_SMARTREFLEX=y +CONFIG_OMAP_SMARTREFLEX_CLASS3=y CONFIG_OMAP_RESET_CLOCKS=y CONFIG_OMAP_MUX_DEBUG=y CONFIG_ARM_THUMBEE=y @@ -34,6 +35,14 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200" CONFIG_KEXEC=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_HOTPLUG=y +CONFIG_CPU_IDLE=y CONFIG_FPE_NWFPE=y CONFIG_BINFMT_MISC=y CONFIG_PM_DEBUG=y @@ -64,6 +73,8 @@ CONFIG_MAC80211=m CONFIG_MAC80211_RC_PID=y CONFIG_MAC80211_RC_DEFAULT_PID=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_CONNECTOR=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y @@ -219,13 +230,33 @@ CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y CONFIG_SCHEDSTATS=y CONFIG_TIMER_STATS=y +CONFIG_DEBUG_SLAB=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_RT_MUTEXES=y CONFIG_PROVE_LOCKING=y +CONFIG_SPARSE_RCU_POINTER=y +CONFIG_DEBUG_LOCKDEP=y CONFIG_DEBUG_SPINLOCK_SLEEP=y -# CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_NOTIFIERS=y +CONFIG_RCU_CPU_STALL_TIMEOUT=120 +CONFIG_DEBUG_PER_CPU_MAPS=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y CONFIG_SECURITY=y CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig index 8b0c717..1d01ddd 100644 --- a/arch/arm/configs/viper_defconfig +++ b/arch/arm/configs/viper_defconfig @@ -142,7 +142,7 @@ CONFIG_USB_GADGETFS=m CONFIG_USB_FILE_STORAGE=m CONFIG_USB_G_SERIAL=m CONFIG_USB_G_PRINTER=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=m CONFIG_RTC_DRV_SA1100=m CONFIG_EXT2_FS=m diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig index 5b55041..721832f 100644 --- a/arch/arm/configs/xcep_defconfig +++ b/arch/arm/configs/xcep_defconfig @@ -73,7 +73,7 @@ CONFIG_SENSORS_MAX6650=m # CONFIG_VGA_CONSOLE is not set # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_SA1100=m CONFIG_DMADEVICES=y # CONFIG_DNOTIFY is not set diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig index 960f655..59577ad 100644 --- a/arch/arm/configs/zeus_defconfig +++ b/arch/arm/configs/zeus_defconfig @@ -158,7 +158,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_PXA=m CONFIG_EXT2_FS=y diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 16bd480..8dee14a 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -45,23 +45,25 @@ #define L2X0_CLEAN_INV_LINE_PA 0x7F0 #define L2X0_CLEAN_INV_LINE_IDX 0x7F8 #define L2X0_CLEAN_INV_WAY 0x7FC -#define L2X0_LOCKDOWN_WAY_D 0x900 -#define L2X0_LOCKDOWN_WAY_I 0x904 +#define L2X0_LOCKDOWN_WAY_D0 0x900 +#define L2X0_LOCKDOWN_WAY_D1 0x908 +#define L2X0_LOCKDOWN_WAY_I0 0x904 +#define L2X0_LOCKDOWN_WAY_I1 0x90C #define L2X0_TEST_OPERATION 0xF00 #define L2X0_LINE_DATA 0xF10 #define L2X0_LINE_TAG 0xF30 #define L2X0_DEBUG_CTRL 0xF40 #define L2X0_PREFETCH_CTRL 0xF60 #define L2X0_POWER_CTRL 0xF80 -#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) -#define L2X0_STNDBY_MODE_EN (1 << 0) +#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) +#define L2X0_STNDBY_MODE_EN (1 << 0) /* Registers shifts and masks */ #define L2X0_CACHE_ID_PART_MASK (0xf << 6) #define L2X0_CACHE_ID_PART_L210 (1 << 6) #define L2X0_CACHE_ID_PART_L310 (3 << 6) -#define L2X0_AUX_CTRL_MASK 0xc0000fff +#define L2X0_AUX_CTRL_MASK 0xd0000fff #define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 #define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 #define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x3 << 17) @@ -72,6 +74,10 @@ #define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 #define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 +#define L2X0_PREFETCH_DATA_PREFETCH_SHIFT 28 +#define L2X0_PREFETCH_INTSTR_PREFETCH_SHIFT 29 +#define L2X0_PREFETCH_DOUBLE_LINEFILL_SHIFT 30 + #ifndef __ASSEMBLY__ extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); #endif diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 8ec535e..35c3fc9 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -97,8 +97,22 @@ extern void cpu_resume(void); #ifdef CONFIG_MMU +#ifdef CONFIG_SMP + +#define cpu_switch_mm(pgd, mm) \ + ({ \ + unsigned long flags; \ + local_irq_save(flags); \ + cpu_do_switch_mm(virt_to_phys(pgd), mm); \ + local_irq_restore(flags); \ + }) + +#else /* SMP */ + #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) +#endif + #define cpu_get_pgd() \ ({ \ unsigned long pg; \ diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index a701e42..0cdd7b4 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -76,6 +76,9 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) unsigned long dt_root; const char *model; + if (!dt_phys) + return NULL; + devtree = phys_to_virt(dt_phys); /* check device tree validity */ diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index e8d8856..90c62cd 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -435,6 +435,10 @@ __irq_usr: usr_entry kuser_cmpxchg_check +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + get_thread_info tsk #ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count @@ -453,7 +457,7 @@ __irq_usr: #endif mov why, #0 - b ret_to_user + b ret_to_user_from_irq UNWIND(.fnend ) ENDPROC(__irq_usr) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 1e7b04a..b2a27b6 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -64,6 +64,7 @@ work_resched: ENTRY(ret_to_user) ret_slow_syscall: disable_irq @ disable interrupts +ENTRY(ret_to_user_from_irq) ldr r1, [tsk, #TI_FLAGS] tst r1, #_TIF_WORK_MASK bne work_pending @@ -75,6 +76,7 @@ no_work_pending: arch_ret_to_user r1, lr restore_user_regs fast = 0, offset = 0 +ENDPROC(ret_to_user_from_irq) ENDPROC(ret_to_user) /* diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 344e52b..e64ed87 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -278,6 +278,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); + static bool booted; printk("CPU%u: Booted secondary processor\n", cpu); @@ -313,7 +314,9 @@ asmlinkage void __cpuinit secondary_start_kernel(void) */ percpu_timer_setup(); - calibrate_delay(); + if (!booted) + calibrate_delay(); + booted = true; smp_store_cpu_info(cpu); diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 60636f4..dbf58d4 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -10,21 +10,29 @@ */ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/err.h> #include <linux/smp.h> #include <linux/jiffies.h> #include <linux/clockchips.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/percpu.h> #include <asm/smp_twd.h> #include <asm/hardware/gic.h> +#define TWD_MIN_RANGE 4 + /* set up by the platform code */ void __iomem *twd_base; +static struct clk *twd_clk; static unsigned long twd_timer_rate; +static DEFINE_PER_CPU(struct clock_event_device *, twd_ce); static void twd_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) @@ -80,6 +88,49 @@ int twd_timer_ack(void) return 0; } +/* + * Updates clockevent frequency when the cpu frequency changes. + * Called on the cpu that is changing frequency with interrupts disabled. + */ +static void twd_update_frequency(void *data) +{ + twd_timer_rate = clk_get_rate(twd_clk); + + clockevents_reconfigure(__get_cpu_var(twd_ce), twd_timer_rate, + TWD_MIN_RANGE); +} + +static int twd_cpufreq_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct cpufreq_freqs *freqs = data; + + /* + * The twd clock events must be reprogrammed to account for the new + * frequency. The timer is local to a cpu, so cross-call to the + * changing cpu. + */ + if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) + smp_call_function_single(freqs->cpu, twd_update_frequency, + NULL, 1); + + return NOTIFY_OK; +} + +static struct notifier_block twd_cpufreq_nb = { + .notifier_call = twd_cpufreq_transition, +}; + +static int twd_cpufreq_init(void) +{ + if (!IS_ERR_OR_NULL(twd_clk)) + return cpufreq_register_notifier(&twd_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); + + return 0; +} +core_initcall(twd_cpufreq_init); + static void __cpuinit twd_calibrate_rate(void) { unsigned long count; @@ -124,7 +175,16 @@ static void __cpuinit twd_calibrate_rate(void) */ void __cpuinit twd_timer_setup(struct clock_event_device *clk) { - twd_calibrate_rate(); + if (twd_clk == NULL) { + twd_clk = clk_get_sys("smp_twd", NULL); + if (IS_ERR_OR_NULL(twd_clk)) + pr_warn("%s: no clock found\n", __func__); + } + + if (!IS_ERR_OR_NULL(twd_clk)) + twd_timer_rate = clk_get_rate(twd_clk); + else + twd_calibrate_rate(); clk->name = "local_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | @@ -132,13 +192,16 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->rating = 350; clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; - clk->shift = 20; - clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift); + + clockevents_calc_mult_shift(clk, twd_timer_rate, TWD_MIN_RANGE); + clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); clk->min_delta_ns = clockevent_delta2ns(0xf, clk); /* Make sure our local interrupt controller has this enabled */ gic_enable_ppi(clk->irq); + __get_cpu_var(twd_ce) = clk; + clockevents_register_device(clk); } diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index d52eec2..6807cb1 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -139,7 +139,7 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) fs = get_fs(); set_fs(KERNEL_DS); - for (i = -4; i < 1; i++) { + for (i = -4; i < 1 + !!thumb; i++) { unsigned int val, bad; if (thumb) @@ -563,7 +563,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) if (!pmd_present(*pmd)) goto bad_access; pte = pte_offset_map_lock(mm, pmd, addr, &ptl); - if (!pte_present(*pte) || !pte_dirty(*pte)) { + if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) { pte_unmap_unlock(pte, ptl); goto bad_access; } diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 4e66881..fc4e98e 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -494,7 +494,7 @@ static struct platform_device da850_mcasp_device = { .resource = da850_mcasp_resources, }; -struct platform_device davinci_pcm_device = { +static struct platform_device davinci_pcm_device = { .name = "davinci-pcm-audio", .id = -1, }; diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 8f4f736..806a2f0 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -298,7 +298,7 @@ static void davinci_init_wdt(void) /*-------------------------------------------------------------------------*/ -struct platform_device davinci_pcm_device = { +static struct platform_device davinci_pcm_device = { .name = "davinci-pcm-audio", .id = -1, }; diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index a0b8388..e722139 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -252,9 +252,11 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct davinci_gpio_regs __iomem *g = irq2regs(irq); + struct davinci_gpio_regs __iomem *g; u32 mask = 0xffff; + g = (__force struct davinci_gpio_regs __iomem *) irq_desc_get_handler_data(desc); + /* we only care about one bank */ if (irq & 1) mask <<= 16; @@ -422,8 +424,7 @@ static int __init davinci_gpio_irq_setup(void) /* set up all irqs in this bank */ irq_set_chained_handler(bank_irq, gpio_irq_handler); - irq_set_chip_data(bank_irq, (__force void *)g); - irq_set_handler_data(bank_irq, (void *)irq); + irq_set_handler_data(bank_irq, (__force void *)g); for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { irq_set_chip(irq, &gpio_irqchip); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 8207954..1d4b65f 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -402,11 +402,15 @@ static struct resource ep93xx_eth_resource[] = { } }; +static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); + static struct platform_device ep93xx_eth_device = { .name = "ep93xx-eth", .id = -1, .dev = { - .platform_data = &ep93xx_eth_data, + .platform_data = &ep93xx_eth_data, + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &ep93xx_eth_dma_mask, }, .num_resources = ARRAY_SIZE(ep93xx_eth_resource), .resource = ep93xx_eth_resource, diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index b92c1e5..1435fc3 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -91,6 +91,11 @@ config EXYNOS4_SETUP_FIMC help Common setup code for the camera interfaces. +config EXYNOS4_SETUP_USB_PHY + bool + help + Common setup code for USB PHY controller + # machine support menu "EXYNOS4 Machines" @@ -176,6 +181,7 @@ config MACH_NURI select EXYNOS4_SETUP_I2C3 select EXYNOS4_SETUP_I2C5 select EXYNOS4_SETUP_SDHCI + select EXYNOS4_SETUP_USB_PHY select SAMSUNG_DEV_PWM help Machine support for Samsung Mobile NURI Board. diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index a9bb94f..60fe5ec 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -56,4 +56,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o -obj-$(CONFIG_USB_SUPPORT) += usb-phy.o +obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY) += setup-usb-phy.o diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 08813a6..9babe44 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -98,7 +98,7 @@ static struct map_desc exynos4_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_USB_HSPHY, + .virtual = (unsigned long)S3C_VA_USB_HSPHY, .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY), .length = SZ_4K, .type = MT_DEVICE, diff --git a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h index 703118d..c337cf3 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h +++ b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h @@ -11,7 +11,7 @@ #ifndef __PLAT_S5P_REGS_USB_PHY_H #define __PLAT_S5P_REGS_USB_PHY_H -#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY) +#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY) #define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00) #define PHY1_HSIC_NORMAL_MASK (0xf << 9) diff --git a/arch/arm/mach-exynos4/usb-phy.c b/arch/arm/mach-exynos4/setup-usb-phy.c index 0883c1b..0883c1b 100644 --- a/arch/arm/mach-exynos4/usb-phy.c +++ b/arch/arm/mach-exynos4/setup-usb-phy.c diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c index 86b9fa0..ebb8f38 100644 --- a/arch/arm/mach-exynos4/time.c +++ b/arch/arm/mach-exynos4/time.c @@ -206,6 +206,7 @@ static cycle_t exynos4_pwm4_read(struct clocksource *cs) return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40)); } +#ifdef CONFIG_PM static void exynos4_pwm4_resume(struct clocksource *cs) { unsigned long pclk; @@ -218,6 +219,7 @@ static void exynos4_pwm4_resume(struct clocksource *cs) exynos4_pwm_init(4, ~0); exynos4_pwm_start(4, 1); } +#endif struct clocksource pwm_clocksource = { .name = "pwm_timer4", diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 5f1f986..121ad1d 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -103,6 +103,7 @@ static void __init footbridge_timer_init(void) clockevents_calc_mult_shift(ce, mem_fclk_21285, 5); ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce); ce->min_delta_ns = clockevent_delta2ns(0x000004, ce); + ce->cpumask = cpumask_of(smp_processor_id()); clockevents_register_device(ce); } diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S index 30b971d..1be2eeb 100644 --- a/arch/arm/mach-footbridge/include/mach/debug-macro.S +++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S @@ -26,6 +26,7 @@ #include <asm/hardware/debug-8250.S> #else +#include <mach/hardware.h> /* For EBSA285 debugging */ .equ dc21285_high, ARMCSR_BASE & 0xff000000 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff @@ -36,8 +37,8 @@ .else mov \rp, #0 .endif - orr \rv, \rp, #0x42000000 - orr \rp, \rp, #dc21285_high + orr \rv, \rp, #dc21285_high + orr \rp, \rp, #0x42000000 .endm .macro senduart,rd,rx diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 38b95e9..63621f1 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -23,6 +23,8 @@ #include <linux/io.h> #include <asm/mach/time.h> +#include <asm/hardware/gic.h> + #include <mach/msm_iomap.h> #include <mach/cpu.h> @@ -55,10 +57,12 @@ enum timer_location { #if defined(CONFIG_ARCH_QSD8X50) #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */ #define MSM_DGT_SHIFT (0) -#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \ - defined(CONFIG_ARCH_MSM8960) +#elif defined(CONFIG_ARCH_MSM7X30) #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */ #define MSM_DGT_SHIFT (0) +#elif defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) +#define DGT_HZ (27000000 / 4) /* 27 MHz (PXO) / 4 by default */ +#define MSM_DGT_SHIFT (0) #else #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */ #define MSM_DGT_SHIFT (5) @@ -100,7 +104,11 @@ static cycle_t msm_read_timer_count(struct clocksource *cs) { struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource); - return readl(clk->global_counter); + /* + * Shift timer count down by a constant due to unreliable lower bits + * on some targets. + */ + return readl(clk->global_counter) >> clk->shift; } static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt) diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c index 65157a3..54add60 100644 --- a/arch/arm/mach-mxs/ocotp.c +++ b/arch/arm/mach-mxs/ocotp.c @@ -16,6 +16,8 @@ #include <linux/err.h> #include <linux/mutex.h> +#include <asm/processor.h> /* for cpu_relax() */ + #include <mach/mxs.h> #define OCOTP_WORD_OFFSET 0x20 diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index af98117..9600410 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -4,14 +4,17 @@ # Common support obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o -obj-y += clock.o clock_data.o opp_data.o reset.o +obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o +# CPUFREQ driver +obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o + # Power Management -obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o +obj-$(CONFIG_PM) += pm.o sleep.o # DSP obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index d855934..f5a5220 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -284,14 +284,15 @@ static int __init omap1_system_dma_init(void) dma_base = ioremap(res[0].start, resource_size(&res[0])); if (!dma_base) { pr_err("%s: Unable to ioremap\n", __func__); - return -ENODEV; + ret = -ENODEV; + goto exit_device_put; } ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); - goto exit_device_del; + goto exit_device_put; } p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); @@ -299,7 +300,7 @@ static int __init omap1_system_dma_init(void) dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", __func__, pdev->name); ret = -ENOMEM; - goto exit_device_put; + goto exit_device_del; } d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); @@ -380,10 +381,10 @@ exit_release_d: kfree(d); exit_release_p: kfree(p); -exit_device_put: - platform_device_put(pdev); exit_device_del: platform_device_del(pdev); +exit_device_put: + platform_device_put(pdev); return ret; } diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/mach-omap1/omap1-cpufreq.c index da4f68d..7c5216e 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/mach-omap1/omap1-cpufreq.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/plat-omap/cpu-omap.c + * OMAP1 cpufreq driver * * CPU frequency scaling for OMAP * @@ -8,6 +8,9 @@ * * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * 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. @@ -21,25 +24,20 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/opp.h> -#include <mach/hardware.h> -#include <plat/clock.h> #include <asm/system.h> -#define VERY_HI_RATE 900000000 +#include <plat/clock.h> +#include <plat/omap-pm.h> -static struct cpufreq_frequency_table *freq_table; +#include <mach/hardware.h> -#ifdef CONFIG_ARCH_OMAP1 -#define MPU_CLK "mpu" -#else -#define MPU_CLK "virt_prcm_set" -#endif +#define VERY_HI_RATE 900000000 +static struct cpufreq_frequency_table *freq_table; static struct clk *mpu_clk; -/* TODO: Add support for SDRAM timing changes */ - static int omap_verify_speed(struct cpufreq_policy *policy) { if (freq_table) @@ -91,21 +89,22 @@ static int omap_target(struct cpufreq_policy *policy, return ret; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + #ifdef CONFIG_CPU_FREQ_DEBUG - printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", - freqs.old, freqs.new); + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); #endif ret = clk_set_rate(mpu_clk, freqs.new * 1000); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return ret; } -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) +static int __init omap_cpu_init(struct cpufreq_policy *policy) { int result = 0; - mpu_clk = clk_get(NULL, MPU_CLK); + mpu_clk = clk_get(NULL, "mpu"); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); @@ -115,6 +114,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = omap_getspeed(0); clk_init_cpufreq_table(&freq_table); + if (freq_table) { result = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (!result) @@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) VERY_HI_RATE) / 1000; } + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(0); + /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; @@ -151,7 +155,7 @@ static struct cpufreq_driver omap_driver = { .get = omap_getspeed, .init = omap_cpu_init, .exit = omap_cpu_exit, - .name = "omap", + .name = "omap1", .attr = omap_cpufreq_attr, }; @@ -160,12 +164,12 @@ static int __init omap_cpufreq_init(void) return cpufreq_register_driver(&omap_driver); } -arch_initcall(omap_cpufreq_init); - -/* - * if ever we want to remove this, upon cleanup call: - * - * cpufreq_unregister_driver() - * cpufreq_frequency_table_put_attr() - */ +static void __exit omap_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&omap_driver); +} +MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs"); +MODULE_LICENSE("GPL"); +module_init(omap_cpufreq_init); +module_exit(omap_cpufreq_exit); diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c index fe31d93..334fb88 100644 --- a/arch/arm/mach-omap1/pm_bus.c +++ b/arch/arm/mach-omap1/pm_bus.c @@ -56,9 +56,13 @@ static struct dev_power_domain default_power_domain = { USE_PLATFORM_PM_SLEEP_OPS }, }; +#define OMAP1_PWR_DOMAIN (&default_power_domain) +#else +#define OMAP1_PWR_DOMAIN NULL +#endif /* CONFIG_PM_RUNTIME */ static struct pm_clk_notifier_block platform_bus_notifier = { - .pwr_domain = &default_power_domain, + .pwr_domain = OMAP1_PWR_DOMAIN, .con_ids = { "ick", "fck", NULL, }, }; @@ -72,4 +76,4 @@ static int __init omap1_pm_runtime_init(void) return 0; } core_initcall(omap1_pm_runtime_init); -#endif /* CONFIG_PM_RUNTIME */ + diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 19d5891..ef7e12f 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -314,6 +314,7 @@ config MACH_OMAP_4430SDP select OMAP_PACKAGE_CBL select OMAP_PACKAGE_CBS select REGULATOR_FIXED_VOLTAGE + select OMAP_TPS6236X config MACH_OMAP4_PANDA bool "OMAP4 Panda Board" @@ -342,6 +343,18 @@ config OMAP3_SDRC_AC_TIMING wish to say no. Selecting yes without understanding what is going on could result in system crashes; +config OMAP_TPS6236X + bool + +config OMAP_ALLOW_OSWR + bool "Enable Open Switch Retention" + depends on ARCH_OMAP4 + default n + help + Select this option to enable OSWR support. + Which means the Logic of power domains can be lost now + unlike the CSWR wherein the logic is retained + endmenu endif diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b148077..07c5d28 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \ - common.o gpio.o dma.o wd_timer.o + common.o gpio.o dma.o wd_timer.o omap_pmic.o omap-2-3-common = irq.o sdrc.o hwmod-common = omap_hwmod.o \ @@ -19,12 +19,14 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_TWL4030_CORE) += omap_twl.o +obj-$(CONFIG_OMAP_TPS6236X) += omap_tps6236x.o # SMP support ONLY available for OMAP4 obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o -obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o +obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o \ + omap-wakeupgen.o plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec) @@ -56,19 +58,25 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o endif +# CPUFREQ driver +obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o + # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ cpuidle34xx.o -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o \ + omap4-mpuss-lowpower.o sleep44xx.o \ + cpuidle44xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec) +AFLAGS_sleep44xx.o :=-Wa,-march=armv7-a$(plus_sec) ifeq ($(CONFIG_PM_VERBOSE),y) CFLAGS_pm_bus.o += -DDEBUG @@ -79,19 +87,20 @@ endif # PRCM obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \ - vc3xxx_data.o vp3xxx_data.o + vc3xxx_data.o vp3xxx_data.o dvfs.o # XXX The presence of cm2xxx_3xxx.o on the line below is temporary and # will be removed once the OMAP4 part of the codebase is converted to # use OMAP4-specific PRCM functions. obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \ cm44xx.o prcm_mpu44xx.o \ prminst44xx.o vc44xx_data.o \ - vp44xx_data.o + vp44xx_data.o dvfs.o # OMAP voltage domains ifeq ($(CONFIG_PM),y) -voltagedomain-common := voltage.o -obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) +voltagedomain-common := voltage.o vc.o vp.o +obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) \ + voltagedomains2xxx_data.o obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \ voltagedomains3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \ @@ -157,13 +166,13 @@ obj-$(CONFIG_OMAP3_EMU) += emu.o obj-$(CONFIG_ARCH_OMAP3) += omap_l3_smx.o obj-$(CONFIG_ARCH_OMAP4) += omap_l3_noc.o +# LDO stuff +obj-$(CONFIG_ARCH_OMAP4) += omap4_trim_quirks.o + obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o mailbox_mach-objs := mailbox.o -obj-$(CONFIG_OMAP_IOMMU) += iommu2.o - -iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o -obj-y += $(iommu-m) $(iommu-y) +obj-$(CONFIG_OMAP_IOMMU) += iommu2.o omap-iommu.o i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o obj-y += $(i2c-omap-m) $(i2c-omap-y) @@ -270,3 +279,5 @@ disp-$(CONFIG_OMAP2_DSS) := display.o obj-y += $(disp-m) $(disp-y) obj-y += common-board-devices.o + +obj-$(CONFIG_OMAP_REMOTE_PROC) += remoteproc.o diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index d54969b..5de6eac 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -26,13 +26,13 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/gpio.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <mach/gpio.h> #include <plat/board.h> #include <plat/common.h> #include <plat/gpmc.h> diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index ae2963a..5dac974 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -622,19 +622,19 @@ static struct omap_device_pad serial3_pads[] __initdata = { OMAP_MUX_MODE0), }; -static struct omap_board_data serial1_data = { +static struct omap_board_data serial1_data __initdata = { .id = 0, .pads = serial1_pads, .pads_cnt = ARRAY_SIZE(serial1_pads), }; -static struct omap_board_data serial2_data = { +static struct omap_board_data serial2_data __initdata = { .id = 1, .pads = serial2_pads, .pads_cnt = ARRAY_SIZE(serial2_pads), }; -static struct omap_board_data serial3_data = { +static struct omap_board_data serial3_data __initdata = { .id = 2, .pads = serial3_pads, .pads_cnt = ARRAY_SIZE(serial3_pads), diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 2647a95..541ca0e 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -44,6 +44,7 @@ #include "timer-gp.h" #include "control.h" #include "common-board-devices.h" +#include "pm.h" #define ETH_KS8851_IRQ 34 #define ETH_KS8851_POWER_ON 48 @@ -58,6 +59,8 @@ #define LED_PWM2OFF 0x04 #define TWL6030_TOGGLE3 0x92 +#define TPS62361_GPIO 7 + static const int sdp4430_keymap[] = { KEY(0, 0, KEY_E), KEY(0, 1, KEY_R), @@ -264,7 +267,7 @@ static struct gpio sdp4430_eth_gpios[] __initdata = { { ETH_KS8851_IRQ, GPIOF_IN, "eth_irq" }, }; -static int omap_ethernet_init(void) +static int __init omap_ethernet_init(void) { int status; @@ -317,6 +320,7 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = -EINVAL, .nonremovable = true, .ocr_mask = MMC_VDD_29_30, + .no_off_init = true, }, { .mmc = 1, @@ -801,19 +805,19 @@ static struct omap_device_pad serial4_pads[] __initdata = { OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), }; -static struct omap_board_data serial2_data = { +static struct omap_board_data serial2_data __initdata = { .id = 1, .pads = serial2_pads, .pads_cnt = ARRAY_SIZE(serial2_pads), }; -static struct omap_board_data serial3_data = { +static struct omap_board_data serial3_data __initdata = { .id = 2, .pads = serial3_pads, .pads_cnt = ARRAY_SIZE(serial3_pads), }; -static struct omap_board_data serial4_data = { +static struct omap_board_data serial4_data __initdata = { .id = 3, .pads = serial4_pads, .pads_cnt = ARRAY_SIZE(serial4_pads), @@ -849,7 +853,7 @@ static void __init omap_4430sdp_init(void) if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; - omap4_mux_init(board_mux, package); + omap4_mux_init(board_mux, NULL, package); omap_board_config = sdp4430_config; omap_board_config_size = ARRAY_SIZE(sdp4430_config); @@ -876,6 +880,14 @@ static void __init omap_4430sdp_init(void) pr_err("Keypad initialization failed: %d\n", status); omap_4430sdp_display_init(); + + if (cpu_is_omap446x()) { + /* Vsel0 = gpio, vsel1 = gnd */ + status = omap_tps6236x_board_setup(true, TPS62361_GPIO, -1, + OMAP_PIN_OFF_OUTPUT_HIGH, -1); + if (status) + pr_err("TPS62361 initialization failed: %d\n", status); + } } static void __init omap_4430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index f3beb8e..b124bdf 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -27,13 +27,13 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/smc91x.h> +#include <linux/gpio.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/flash.h> -#include <mach/gpio.h> #include <plat/led.h> #include <plat/usb.h> #include <plat/board.h> diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index c63115b..77456de 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -63,8 +63,6 @@ #define SB_T35_SMSC911X_CS 4 #define SB_T35_SMSC911X_GPIO 65 -#define NAND_BLOCK_SIZE SZ_128K - #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include <linux/smsc911x.h> #include <plat/gpmc-smsc911x.h> diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index 08f08e8..c3a9fd3 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -48,6 +48,7 @@ #include "mux.h" #include "control.h" +#include "common-board-devices.h" #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) static struct gpio_led cm_t3517_leds[] = { @@ -177,7 +178,7 @@ static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = { .reset_gpio_port[2] = -EINVAL, }; -static int cm_t3517_init_usbh(void) +static int __init cm_t3517_init_usbh(void) { int err; @@ -203,8 +204,6 @@ static inline int cm_t3517_init_usbh(void) #endif #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) -#define NAND_BLOCK_SIZE SZ_128K - static struct mtd_partition cm_t3517_nand_partitions[] = { { .name = "xloader", diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index cf520d7..34956ec 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -61,8 +61,6 @@ #include "timer-gp.h" #include "common-board-devices.h" -#define NAND_BLOCK_SIZE SZ_128K - #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index be71426..7f21d24 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -54,8 +54,6 @@ #include "pm.h" #include "common-board-devices.h" -#define NAND_BLOCK_SIZE SZ_128K - /* * OMAP3 Beagle revision * Run time detection of Beagle revision is done by reading GPIO. @@ -106,6 +104,9 @@ static void __init omap3_beagle_init_rev(void) beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1) | (gpio_get_value(173) << 2); + gpio_free_array(omap3_beagle_rev_gpios, + ARRAY_SIZE(omap3_beagle_rev_gpios)); + switch (beagle_rev) { case 7: printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n"); @@ -579,6 +580,9 @@ static void __init omap3_beagle_init(void) omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, ARRAY_SIZE(omap3beagle_nand_partitions)); + /* Ensure msecure is mux'd to be able to set the RTC. */ + omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH); + /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 1d10736..23f71d4 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -30,6 +30,7 @@ #include <linux/leds.h> #include <linux/input.h> #include <linux/input/matrix_keypad.h> +#include <linux/gpio.h> #include <linux/gpio_keys.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> @@ -41,7 +42,6 @@ #include <plat/board.h> #include <plat/common.h> -#include <mach/gpio.h> #include <mach/hardware.h> #include <plat/mcspi.h> #include <plat/usb.h> @@ -57,8 +57,6 @@ #define PANDORA_WIFI_NRESET_GPIO 23 #define OMAP3_PANDORA_TS_GPIO 94 -#define NAND_BLOCK_SIZE SZ_128K - static struct mtd_partition omap3pandora_nand_partitions[] = { { .name = "xloader", @@ -86,7 +84,8 @@ static struct mtd_partition omap3pandora_nand_partitions[] = { static struct omap_nand_platform_data pandora_nand_data = { .cs = 0, - .devsize = 1, /* '0' for 8-bit, '1' for 16-bit device */ + .devsize = NAND_BUSWIDTH_16, + .xfer_type = NAND_OMAP_PREFETCH_DMA, .parts = omap3pandora_nand_partitions, .nr_parts = ARRAY_SIZE(omap3pandora_nand_partitions), }; diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index 82872d7..5f649fa 100644 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -56,8 +56,6 @@ #include <asm/setup.h> -#define NAND_BLOCK_SIZE SZ_128K - #define OMAP3_AC_GPIO 136 #define OMAP3_TS_GPIO 162 #define TB_BL_PWM_TIMER 9 diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 90485fc..10ce8d0 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -380,6 +380,24 @@ static struct regulator_init_data omap4_panda_clk32kg = { }, }; +static void omap4_audio_conf(void) +{ + /* twl6040 naudint */ + omap_mux_init_signal("sys_nirq2.sys_nirq2", \ + OMAP_PIN_INPUT_PULLUP); +} + +static struct twl4030_codec_audio_data twl6040_audio = { + /* Add audio only data */ +}; + +static struct twl4030_codec_data twl6040_codec = { + .audio = &twl6040_audio, + .audpwron_gpio = 127, + .naudint_irq = OMAP44XX_IRQ_SYS_2N, + .irq_base = TWL6040_CODEC_IRQ_BASE, +}; + static struct twl4030_platform_data omap4_panda_twldata = { .irq_base = TWL6030_IRQ_BASE, .irq_end = TWL6030_IRQ_END, @@ -395,6 +413,9 @@ static struct twl4030_platform_data omap4_panda_twldata = { .vaux3 = &omap4_panda_vaux3, .clk32kg = &omap4_panda_clk32kg, .usb = &omap4_usbphy_data, + + /* children */ + .codec = &twl6040_codec, }; /* @@ -526,19 +547,19 @@ static struct omap_device_pad serial4_pads[] __initdata = { OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), }; -static struct omap_board_data serial2_data = { +static struct omap_board_data serial2_data __initdata = { .id = 1, .pads = serial2_pads, .pads_cnt = ARRAY_SIZE(serial2_pads), }; -static struct omap_board_data serial3_data = { +static struct omap_board_data serial3_data __initdata = { .id = 2, .pads = serial3_pads, .pads_cnt = ARRAY_SIZE(serial3_pads), }; -static struct omap_board_data serial4_data = { +static struct omap_board_data serial4_data __initdata = { .id = 3, .pads = serial4_pads, .pads_cnt = ARRAY_SIZE(serial4_pads), @@ -687,14 +708,21 @@ static void __init omap4_panda_init(void) if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; - omap4_mux_init(board_mux, package); + omap4_mux_init(board_mux, NULL, package); if (wl12xx_set_platform_data(&omap_panda_wlan_data)) pr_err("error setting wl12xx data\n"); omap4_panda_i2c_init(); + omap4_audio_conf(); platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); - platform_device_register(&omap_vwlan_device); +/* + * This is temporaray. With WLAN regsitering, we see that UART2 is not + * idling on panda and CORE RET is not happening. So removing this FTM. + * Later will be enabled. + * + * platform_device_register(&omap_vwlan_device); + */ board_serial_init(); omap4_twl6030_hsmmc_init(mmc); omap4_ehci_init(); diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 1555918..175e1ab 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -24,6 +24,7 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/gpio.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/i2c/twl.h> @@ -45,7 +46,6 @@ #include <plat/common.h> #include <video/omapdss.h> #include <video/omap-panel-generic-dpi.h> -#include <mach/gpio.h> #include <plat/gpmc.h> #include <mach/hardware.h> #include <plat/nand.h> @@ -65,8 +65,6 @@ #define OVERO_GPIO_USBH_CPEN 168 #define OVERO_GPIO_USBH_NRESET 183 -#define NAND_BLOCK_SIZE SZ_128K - #define OVERO_SMSC911X_CS 5 #define OVERO_SMSC911X_GPIO 176 #define OVERO_SMSC911X2_CS 4 diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index f6247e7..9903667 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -488,6 +488,7 @@ static struct regulator_init_data rx51_vmmc2 = { .name = "V28_A", .min_uV = 2800000, .max_uV = 3000000, + .always_on = true, /* due VIO leak to AIC34 VDDs */ .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, @@ -582,7 +583,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n) { /* FIXME this gpio setup is just a placeholder for now */ gpio_request_one(gpio + 6, GPIOF_OUT_INIT_LOW, "backlight_pwm"); - gpio_request_one(gpio + 7, GPIOF_OUT_INIT_HIGH, "speaker_en"); + gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "speaker_en"); return 0; } diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c index c7c6beb..d4683ba 100644 --- a/arch/arm/mach-omap2/board-zoom-display.c +++ b/arch/arm/mach-omap2/board-zoom-display.c @@ -26,7 +26,7 @@ static struct gpio zoom_lcd_gpios[] __initdata = { { LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "lcd qvga" }, }; -static void zoom_lcd_panel_init(void) +static void __init zoom_lcd_panel_init(void) { zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? LCD_PANEL_RESET_GPIO_PROD : diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c index bcffee0..a7e78e4 100644 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ b/arch/arm/mach-omap2/clkt_dpll.c @@ -292,12 +292,14 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) for (n = dd->min_divider; n <= dd->max_divider; n++) { - /* Is the (input clk, divider) pair valid for the DPLL? */ - r = _dpll_test_fint(clk, n); - if (r == DPLL_FINT_UNDERFLOW) - break; - else if (r == DPLL_FINT_INVALID) - continue; + if (cpu_is_omap34xx()) { + /* Is the (input clk, divider)pair valid for the DPLL?*/ + r = _dpll_test_fint(clk, n); + if (r == DPLL_FINT_UNDERFLOW) + break; + else if (r == DPLL_FINT_INVALID) + continue; + } /* Compute the scaled DPLL multiplier, based on the divider */ m = scaled_rt_rp * n; diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 180299e..1334f59 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -32,6 +32,7 @@ #include "clock.h" #include "cm2xxx_3xxx.h" +#include "cm44xx.h" #include "cm-regbits-24xx.h" #include "cm-regbits-34xx.h" @@ -43,6 +44,11 @@ u8 cpu_mask; /* Private functions */ +static void _omap4_module_wait_ready(struct clk *clk) +{ + omap4_cm_wait_module_ready(clk->enable_reg); +} + /** * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE * @clk: struct clk * belonging to the module @@ -190,8 +196,12 @@ int omap2_dflt_clk_enable(struct clk *clk) __raw_writel(v, clk->enable_reg); v = __raw_readl(clk->enable_reg); /* OCP barrier */ - if (clk->ops->find_idlest) - _omap2_module_wait_ready(clk); + if (clk->ops->find_idlest) { + if (cpu_is_omap44xx()) + _omap4_module_wait_ready(clk); + else + _omap2_module_wait_ready(clk); + } return 0; } @@ -219,6 +229,12 @@ void omap2_dflt_clk_disable(struct clk *clk) /* No OCP barrier needed here since it is a disable operation */ } +const struct clkops clkops_omap4_dflt_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap2_clk_dflt_find_idlest, +}; + const struct clkops clkops_omap2_dflt_wait = { .enable = omap2_dflt_clk_enable, .disable = omap2_dflt_clk_disable, @@ -327,6 +343,10 @@ int omap2_clk_enable(struct clk *clk) } } + /* If clockdomain supports hardware control, enable it */ + if (clk->clkdm) + clkdm_allow_idle(clk->clkdm); + return 0; oce_err3: diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index e10ff2b..bfc8725 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -64,6 +64,9 @@ void omap3_noncore_dpll_disable(struct clk *clk); int omap4_dpllmx_gatectrl_read(struct clk *clk); void omap4_dpllmx_allow_gatectrl(struct clk *clk); void omap4_dpllmx_deny_gatectrl(struct clk *clk); +int omap4460_mpu_dpll_set_rate(struct clk *clk, unsigned long rate); +long omap4460_mpu_dpll_round_rate(struct clk *clk, unsigned long rate); +unsigned long omap4460_mpu_dpll_recalc(struct clk *clk); #ifdef CONFIG_OMAP_RESET_CLOCKS void omap2_clk_disable_unused(struct clk *clk); @@ -132,6 +135,7 @@ extern u8 cpu_mask; extern const struct clkops clkops_omap2_dflt_wait; extern const struct clkops clkops_dummy; extern const struct clkops clkops_omap2_dflt; +extern const struct clkops clkops_omap4_dflt_wait; extern struct clk_functions omap2_clk_functions; extern struct clk *vclk, *sclk; @@ -141,7 +145,9 @@ extern const struct clksel_rate gpt_sys_rates[]; extern const struct clksel_rate gfx_l3_rates[]; extern const struct clksel_rate dsp_ick_rates[]; -#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ) +#ifdef CONFIG_CPU_FREQ + +#ifdef CONFIG_ARCH_OMAP2 extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); #else @@ -149,6 +155,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) #define omap2_clk_exit_cpufreq_table 0 #endif +#ifdef CONFIG_ARCH_OMAP3 +extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); +extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); +#else +#define omap3_clk_init_cpufreq_table 0 +#define omap3_clk_exit_cpufreq_table 0 +#endif + +#endif /* CONFIG_CPU_FREQ */ + extern const struct clkops clkops_omap2_iclk_dflt_wait; extern const struct clkops clkops_omap2_iclk_dflt; extern const struct clkops clkops_omap2_iclk_idle_only; diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 1fc96b9..119e135 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -20,6 +20,8 @@ #include <linux/kernel.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/err.h> +#include <linux/cpufreq.h> #include <plat/clock.h> diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 4d278e7..d332e7b 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -1,7 +1,7 @@ /* - * OMAP4 Clock data + * OMAP44xx Clock data * - * Copyright (C) 2009-2010 Texas Instruments, Inc. + * Copyright (C) 2009-2011 Texas Instruments Incorporated * Copyright (C) 2009-2010 Nokia Corporation * * Paul Walmsley (paul@pwsan.com) @@ -42,6 +42,10 @@ #define OMAP4430_MODULEMODE_HWCTRL 0 #define OMAP4430_MODULEMODE_SWCTRL 1 +static int omap4_virt_l3_set_rate(struct clk *clk, unsigned long rate); +static long omap4_virt_l3_round_rate(struct clk *clk, unsigned long rate); +static unsigned long omap4_virt_l3_recalc(struct clk *clk); + /* Root clocks */ static struct clk extalt_clkin_ck = { @@ -53,7 +57,7 @@ static struct clk extalt_clkin_ck = { static struct clk pad_clks_ck = { .name = "pad_clks_ck", .rate = 12000000, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_CLKSEL_ABE, .enable_bit = OMAP4430_PAD_CLKS_GATE_SHIFT, }; @@ -73,7 +77,7 @@ static struct clk secure_32k_clk_src_ck = { static struct clk slimbus_clk = { .name = "slimbus_clk", .rate = 12000000, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_CLKSEL_ABE, .enable_bit = OMAP4430_SLIMBUS_CLK_GATE_SHIFT, }; @@ -127,42 +131,42 @@ static struct clk virt_38400000_ck = { }; static const struct clksel_rate div_1_0_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_4430 }, + { .div = 1, .val = 0, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_1_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_4430 }, + { .div = 1, .val = 1, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_2_rates[] = { - { .div = 1, .val = 2, .flags = RATE_IN_4430 }, + { .div = 1, .val = 2, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_3_rates[] = { - { .div = 1, .val = 3, .flags = RATE_IN_4430 }, + { .div = 1, .val = 3, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_4_rates[] = { - { .div = 1, .val = 4, .flags = RATE_IN_4430 }, + { .div = 1, .val = 4, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_5_rates[] = { - { .div = 1, .val = 5, .flags = RATE_IN_4430 }, + { .div = 1, .val = 5, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_6_rates[] = { - { .div = 1, .val = 6, .flags = RATE_IN_4430 }, + { .div = 1, .val = 6, .flags = RATE_IN_44XX }, { .div = 0 }, }; static const struct clksel_rate div_1_7_rates[] = { - { .div = 1, .val = 7, .flags = RATE_IN_4430 }, + { .div = 1, .val = 7, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -285,37 +289,37 @@ static struct clk dpll_abe_x2_ck = { }; static const struct clksel_rate div31_1to31_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_4430 }, - { .div = 2, .val = 2, .flags = RATE_IN_4430 }, - { .div = 3, .val = 3, .flags = RATE_IN_4430 }, - { .div = 4, .val = 4, .flags = RATE_IN_4430 }, - { .div = 5, .val = 5, .flags = RATE_IN_4430 }, - { .div = 6, .val = 6, .flags = RATE_IN_4430 }, - { .div = 7, .val = 7, .flags = RATE_IN_4430 }, - { .div = 8, .val = 8, .flags = RATE_IN_4430 }, - { .div = 9, .val = 9, .flags = RATE_IN_4430 }, - { .div = 10, .val = 10, .flags = RATE_IN_4430 }, - { .div = 11, .val = 11, .flags = RATE_IN_4430 }, - { .div = 12, .val = 12, .flags = RATE_IN_4430 }, - { .div = 13, .val = 13, .flags = RATE_IN_4430 }, - { .div = 14, .val = 14, .flags = RATE_IN_4430 }, - { .div = 15, .val = 15, .flags = RATE_IN_4430 }, - { .div = 16, .val = 16, .flags = RATE_IN_4430 }, - { .div = 17, .val = 17, .flags = RATE_IN_4430 }, - { .div = 18, .val = 18, .flags = RATE_IN_4430 }, - { .div = 19, .val = 19, .flags = RATE_IN_4430 }, - { .div = 20, .val = 20, .flags = RATE_IN_4430 }, - { .div = 21, .val = 21, .flags = RATE_IN_4430 }, - { .div = 22, .val = 22, .flags = RATE_IN_4430 }, - { .div = 23, .val = 23, .flags = RATE_IN_4430 }, - { .div = 24, .val = 24, .flags = RATE_IN_4430 }, - { .div = 25, .val = 25, .flags = RATE_IN_4430 }, - { .div = 26, .val = 26, .flags = RATE_IN_4430 }, - { .div = 27, .val = 27, .flags = RATE_IN_4430 }, - { .div = 28, .val = 28, .flags = RATE_IN_4430 }, - { .div = 29, .val = 29, .flags = RATE_IN_4430 }, - { .div = 30, .val = 30, .flags = RATE_IN_4430 }, - { .div = 31, .val = 31, .flags = RATE_IN_4430 }, + { .div = 1, .val = 1, .flags = RATE_IN_44XX }, + { .div = 2, .val = 2, .flags = RATE_IN_44XX }, + { .div = 3, .val = 3, .flags = RATE_IN_44XX }, + { .div = 4, .val = 4, .flags = RATE_IN_44XX }, + { .div = 5, .val = 5, .flags = RATE_IN_44XX }, + { .div = 6, .val = 6, .flags = RATE_IN_44XX }, + { .div = 7, .val = 7, .flags = RATE_IN_44XX }, + { .div = 8, .val = 8, .flags = RATE_IN_44XX }, + { .div = 9, .val = 9, .flags = RATE_IN_44XX }, + { .div = 10, .val = 10, .flags = RATE_IN_44XX }, + { .div = 11, .val = 11, .flags = RATE_IN_44XX }, + { .div = 12, .val = 12, .flags = RATE_IN_44XX }, + { .div = 13, .val = 13, .flags = RATE_IN_44XX }, + { .div = 14, .val = 14, .flags = RATE_IN_44XX }, + { .div = 15, .val = 15, .flags = RATE_IN_44XX }, + { .div = 16, .val = 16, .flags = RATE_IN_44XX }, + { .div = 17, .val = 17, .flags = RATE_IN_44XX }, + { .div = 18, .val = 18, .flags = RATE_IN_44XX }, + { .div = 19, .val = 19, .flags = RATE_IN_44XX }, + { .div = 20, .val = 20, .flags = RATE_IN_44XX }, + { .div = 21, .val = 21, .flags = RATE_IN_44XX }, + { .div = 22, .val = 22, .flags = RATE_IN_44XX }, + { .div = 23, .val = 23, .flags = RATE_IN_44XX }, + { .div = 24, .val = 24, .flags = RATE_IN_44XX }, + { .div = 25, .val = 25, .flags = RATE_IN_44XX }, + { .div = 26, .val = 26, .flags = RATE_IN_44XX }, + { .div = 27, .val = 27, .flags = RATE_IN_44XX }, + { .div = 28, .val = 28, .flags = RATE_IN_44XX }, + { .div = 29, .val = 29, .flags = RATE_IN_44XX }, + { .div = 30, .val = 30, .flags = RATE_IN_44XX }, + { .div = 31, .val = 31, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -345,9 +349,9 @@ static struct clk abe_24m_fclk = { }; static const struct clksel_rate div3_1to4_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_4430 }, - { .div = 2, .val = 1, .flags = RATE_IN_4430 }, - { .div = 4, .val = 2, .flags = RATE_IN_4430 }, + { .div = 1, .val = 0, .flags = RATE_IN_44XX }, + { .div = 2, .val = 1, .flags = RATE_IN_44XX }, + { .div = 4, .val = 2, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -369,8 +373,8 @@ static struct clk abe_clk = { }; static const struct clksel_rate div2_1to2_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_4430 }, - { .div = 2, .val = 1, .flags = RATE_IN_4430 }, + { .div = 1, .val = 0, .flags = RATE_IN_44XX }, + { .div = 2, .val = 1, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -524,6 +528,15 @@ static struct clk dpll_core_m5x2_ck = { .set_rate = &omap2_clksel_set_rate, }; +static struct clk virt_l3_ck = { + .name = "virt_l3_ck", + .parent = &dpll_core_m5x2_ck, + .ops = &clkops_null, + .set_rate = &omap4_virt_l3_set_rate, + .recalc = &omap4_virt_l3_recalc, + .round_rate = &omap4_virt_l3_round_rate, +}; + static const struct clksel div_core_div[] = { { .parent = &dpll_core_m5x2_ck, .rates = div2_1to2_rates }, { .parent = NULL }, @@ -542,10 +555,10 @@ static struct clk div_core_ck = { }; static const struct clksel_rate div4_1to8_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_4430 }, - { .div = 2, .val = 1, .flags = RATE_IN_4430 }, - { .div = 4, .val = 2, .flags = RATE_IN_4430 }, - { .div = 8, .val = 3, .flags = RATE_IN_4430 }, + { .div = 1, .val = 0, .flags = RATE_IN_44XX }, + { .div = 2, .val = 1, .flags = RATE_IN_44XX }, + { .div = 4, .val = 2, .flags = RATE_IN_44XX }, + { .div = 8, .val = 3, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -621,7 +634,7 @@ static struct clk dpll_core_m3x2_ck = { .clksel = dpll_core_m6x2_div, .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_CORE, .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DIV_M3_DPLL_CORE, .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, .recalc = &omap2_clksel_recalc, @@ -774,6 +787,15 @@ static struct clk dpll_mpu_m2_ck = { .set_rate = &omap2_clksel_set_rate, }; +static struct clk virt_dpll_mpu_ck = { + .name = "virt_dpll_mpu_ck", + .parent = &dpll_mpu_ck, + .ops = &clkops_null, + .recalc = &omap4460_mpu_dpll_recalc, + .round_rate = &omap4460_mpu_dpll_round_rate, + .set_rate = &omap4460_mpu_dpll_set_rate, +}; + static struct clk per_hs_clk_div_ck = { .name = "per_hs_clk_div_ck", .parent = &dpll_abe_m3x2_ck, @@ -879,7 +901,7 @@ static struct clk dpll_per_m3x2_ck = { .clksel = dpll_per_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_PER, .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DIV_M3_DPLL_PER, .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, .recalc = &omap2_clksel_recalc, @@ -1099,8 +1121,8 @@ static struct clk func_24mc_fclk = { }; static const struct clksel_rate div2_4to8_rates[] = { - { .div = 4, .val = 0, .flags = RATE_IN_4430 }, - { .div = 8, .val = 1, .flags = RATE_IN_4430 }, + { .div = 4, .val = 0, .flags = RATE_IN_44XX }, + { .div = 8, .val = 1, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -1130,8 +1152,8 @@ static struct clk func_48mc_fclk = { }; static const struct clksel_rate div2_2to4_rates[] = { - { .div = 2, .val = 0, .flags = RATE_IN_4430 }, - { .div = 4, .val = 1, .flags = RATE_IN_4430 }, + { .div = 2, .val = 0, .flags = RATE_IN_44XX }, + { .div = 4, .val = 1, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -1183,8 +1205,8 @@ static struct clk hsmmc6_fclk = { }; static const struct clksel_rate div2_1to8_rates[] = { - { .div = 1, .val = 0, .flags = RATE_IN_4430 }, - { .div = 8, .val = 1, .flags = RATE_IN_4430 }, + { .div = 1, .val = 0, .flags = RATE_IN_44XX }, + { .div = 8, .val = 1, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -1264,6 +1286,13 @@ static struct clk l4_wkup_clk_mux_ck = { .recalc = &omap2_clksel_recalc, }; +static struct clk div_ts_ck = { + .name = "div_ts_ck", + .parent = &l4_wkup_clk_mux_ck, + .ops = &clkops_null, + .recalc = &followparent_recalc, +}; + static const struct clksel per_abe_nc_fclk_div[] = { { .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates }, { .parent = NULL }, @@ -1358,7 +1387,7 @@ static struct clk syc_clk_div_ck = { static struct clk aes1_fck = { .name = "aes1_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4SEC_AES1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_secure_clkdm", @@ -1368,7 +1397,7 @@ static struct clk aes1_fck = { static struct clk aes2_fck = { .name = "aes2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4SEC_AES2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_secure_clkdm", @@ -1378,7 +1407,7 @@ static struct clk aes2_fck = { static struct clk aess_fck = { .name = "aess_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "abe_clkdm", @@ -1388,7 +1417,7 @@ static struct clk aess_fck = { static struct clk bandgap_fclk = { .name = "bandgap_fclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT, .clkdm_name = "l4_wkup_clkdm", @@ -1396,9 +1425,19 @@ static struct clk bandgap_fclk = { .recalc = &followparent_recalc, }; +static struct clk bandgap_ts_fclk = { + .name = "bandgap_ts_fclk", + .ops = &clkops_omap2_dflt, + .enable_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, + .enable_bit = OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT, + .clkdm_name = "l4_wkup_clkdm", + .parent = &div_ts_ck, + .recalc = &followparent_recalc, +}; + static struct clk des3des_fck = { .name = "des3des_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4SEC_DES3DES_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_secure_clkdm", @@ -1439,7 +1478,7 @@ static struct clk dmic_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -1448,7 +1487,7 @@ static struct clk dmic_fck = { static struct clk dsp_fck = { .name = "dsp_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "tesla_clkdm", @@ -1458,7 +1497,7 @@ static struct clk dsp_fck = { static struct clk dss_sys_clk = { .name = "dss_sys_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT, .clkdm_name = "l3_dss_clkdm", @@ -1468,7 +1507,7 @@ static struct clk dss_sys_clk = { static struct clk dss_tv_clk = { .name = "dss_tv_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_TV_CLK_SHIFT, .clkdm_name = "l3_dss_clkdm", @@ -1478,7 +1517,7 @@ static struct clk dss_tv_clk = { static struct clk dss_dss_clk = { .name = "dss_dss_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DSSCLK_SHIFT, .clkdm_name = "l3_dss_clkdm", @@ -1488,7 +1527,7 @@ static struct clk dss_dss_clk = { static struct clk dss_48mhz_clk = { .name = "dss_48mhz_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT, .clkdm_name = "l3_dss_clkdm", @@ -1498,7 +1537,7 @@ static struct clk dss_48mhz_clk = { static struct clk dss_fck = { .name = "dss_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l3_dss_clkdm", @@ -1508,7 +1547,7 @@ static struct clk dss_fck = { static struct clk efuse_ctrl_cust_fck = { .name = "efuse_ctrl_cust_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_cefuse_clkdm", @@ -1518,7 +1557,7 @@ static struct clk efuse_ctrl_cust_fck = { static struct clk emif1_fck = { .name = "emif1_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .flags = ENABLE_ON_INIT, @@ -1529,7 +1568,7 @@ static struct clk emif1_fck = { static struct clk emif2_fck = { .name = "emif2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .flags = ENABLE_ON_INIT, @@ -1550,7 +1589,7 @@ static struct clk fdif_fck = { .clksel = fdif_fclk_div, .clksel_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_FCLK_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -1561,7 +1600,7 @@ static struct clk fdif_fck = { static struct clk fpka_fck = { .name = "fpka_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_secure_clkdm", @@ -1571,7 +1610,7 @@ static struct clk fpka_fck = { static struct clk gpio1_dbclk = { .name = "gpio1_dbclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT, .clkdm_name = "l4_wkup_clkdm", @@ -1581,7 +1620,7 @@ static struct clk gpio1_dbclk = { static struct clk gpio1_ick = { .name = "gpio1_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_wkup_clkdm", @@ -1591,7 +1630,7 @@ static struct clk gpio1_ick = { static struct clk gpio2_dbclk = { .name = "gpio2_dbclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -1601,7 +1640,7 @@ static struct clk gpio2_dbclk = { static struct clk gpio2_ick = { .name = "gpio2_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1611,7 +1650,7 @@ static struct clk gpio2_ick = { static struct clk gpio3_dbclk = { .name = "gpio3_dbclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -1621,7 +1660,7 @@ static struct clk gpio3_dbclk = { static struct clk gpio3_ick = { .name = "gpio3_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1631,7 +1670,7 @@ static struct clk gpio3_ick = { static struct clk gpio4_dbclk = { .name = "gpio4_dbclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -1641,7 +1680,7 @@ static struct clk gpio4_dbclk = { static struct clk gpio4_ick = { .name = "gpio4_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1651,7 +1690,7 @@ static struct clk gpio4_ick = { static struct clk gpio5_dbclk = { .name = "gpio5_dbclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -1661,7 +1700,7 @@ static struct clk gpio5_dbclk = { static struct clk gpio5_ick = { .name = "gpio5_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1671,7 +1710,7 @@ static struct clk gpio5_ick = { static struct clk gpio6_dbclk = { .name = "gpio6_dbclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -1681,7 +1720,7 @@ static struct clk gpio6_dbclk = { static struct clk gpio6_ick = { .name = "gpio6_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1691,7 +1730,7 @@ static struct clk gpio6_ick = { static struct clk gpmc_ick = { .name = "gpmc_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3_2_GPMC_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_2_clkdm", @@ -1713,7 +1752,7 @@ static struct clk gpu_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_GFX_GFX_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SGX_FCLK_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_GFX_GFX_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -1722,7 +1761,7 @@ static struct clk gpu_fck = { static struct clk hdq1w_fck = { .name = "hdq1w_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1742,7 +1781,7 @@ static struct clk hsi_fck = { .clksel = hsi_fclk_div, .clksel_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_24_25_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -1753,7 +1792,7 @@ static struct clk hsi_fck = { static struct clk i2c1_fck = { .name = "i2c1_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1763,7 +1802,7 @@ static struct clk i2c1_fck = { static struct clk i2c2_fck = { .name = "i2c2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1773,7 +1812,7 @@ static struct clk i2c2_fck = { static struct clk i2c3_fck = { .name = "i2c3_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1783,7 +1822,7 @@ static struct clk i2c3_fck = { static struct clk i2c4_fck = { .name = "i2c4_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -1793,7 +1832,7 @@ static struct clk i2c4_fck = { static struct clk ipu_fck = { .name = "ipu_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "ducati_clkdm", @@ -1803,7 +1842,7 @@ static struct clk ipu_fck = { static struct clk iss_ctrlclk = { .name = "iss_ctrlclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_CAM_ISS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT, .clkdm_name = "iss_clkdm", @@ -1813,7 +1852,7 @@ static struct clk iss_ctrlclk = { static struct clk iss_fck = { .name = "iss_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_CAM_ISS_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "iss_clkdm", @@ -1823,7 +1862,7 @@ static struct clk iss_fck = { static struct clk iva_fck = { .name = "iva_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "ivahd_clkdm", @@ -1833,7 +1872,7 @@ static struct clk iva_fck = { static struct clk kbd_fck = { .name = "kbd_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_wkup_clkdm", @@ -1843,7 +1882,7 @@ static struct clk kbd_fck = { static struct clk l3_instr_ick = { .name = "l3_instr_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_instr_clkdm", @@ -1854,7 +1893,7 @@ static struct clk l3_instr_ick = { static struct clk l3_main_3_ick = { .name = "l3_main_3_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_instr_clkdm", @@ -1889,7 +1928,7 @@ static struct clk mcasp_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -1922,7 +1961,7 @@ static struct clk mcbsp1_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -1955,7 +1994,7 @@ static struct clk mcbsp2_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -1988,7 +2027,7 @@ static struct clk mcbsp3_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2020,7 +2059,7 @@ static struct clk mcbsp4_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_SOURCE_24_24_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2029,7 +2068,7 @@ static struct clk mcbsp4_fck = { static struct clk mcpdm_fck = { .name = "mcpdm_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "abe_clkdm", @@ -2039,7 +2078,7 @@ static struct clk mcpdm_fck = { static struct clk mcspi1_fck = { .name = "mcspi1_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2049,7 +2088,7 @@ static struct clk mcspi1_fck = { static struct clk mcspi2_fck = { .name = "mcspi2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2059,7 +2098,7 @@ static struct clk mcspi2_fck = { static struct clk mcspi3_fck = { .name = "mcspi3_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2069,7 +2108,7 @@ static struct clk mcspi3_fck = { static struct clk mcspi4_fck = { .name = "mcspi4_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2085,7 +2124,7 @@ static struct clk mmc1_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2100,7 +2139,7 @@ static struct clk mmc2_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2109,7 +2148,7 @@ static struct clk mmc2_fck = { static struct clk mmc3_fck = { .name = "mmc3_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2119,7 +2158,7 @@ static struct clk mmc3_fck = { static struct clk mmc4_fck = { .name = "mmc4_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2129,7 +2168,7 @@ static struct clk mmc4_fck = { static struct clk mmc5_fck = { .name = "mmc5_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2139,7 +2178,7 @@ static struct clk mmc5_fck = { static struct clk ocp2scp_usb_phy_phy_48m = { .name = "ocp2scp_usb_phy_phy_48m", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2149,7 +2188,7 @@ static struct clk ocp2scp_usb_phy_phy_48m = { static struct clk ocp2scp_usb_phy_ick = { .name = "ocp2scp_usb_phy_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_init_clkdm", @@ -2159,7 +2198,7 @@ static struct clk ocp2scp_usb_phy_ick = { static struct clk ocp_wp_noc_ick = { .name = "ocp_wp_noc_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_instr_clkdm", @@ -2170,7 +2209,7 @@ static struct clk ocp_wp_noc_ick = { static struct clk rng_ick = { .name = "rng_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4SEC_RNG_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_secure_clkdm", @@ -2180,7 +2219,7 @@ static struct clk rng_ick = { static struct clk sha2md5_fck = { .name = "sha2md5_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_secure_clkdm", @@ -2190,7 +2229,7 @@ static struct clk sha2md5_fck = { static struct clk sl2if_ick = { .name = "sl2if_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_IVAHD_SL2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "ivahd_clkdm", @@ -2200,7 +2239,7 @@ static struct clk sl2if_ick = { static struct clk slimbus1_fclk_1 = { .name = "slimbus1_fclk_1", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_FCLK1_SHIFT, .clkdm_name = "abe_clkdm", @@ -2210,7 +2249,7 @@ static struct clk slimbus1_fclk_1 = { static struct clk slimbus1_fclk_0 = { .name = "slimbus1_fclk_0", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_FCLK0_SHIFT, .clkdm_name = "abe_clkdm", @@ -2220,7 +2259,7 @@ static struct clk slimbus1_fclk_0 = { static struct clk slimbus1_fclk_2 = { .name = "slimbus1_fclk_2", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_FCLK2_SHIFT, .clkdm_name = "abe_clkdm", @@ -2230,7 +2269,7 @@ static struct clk slimbus1_fclk_2 = { static struct clk slimbus1_slimbus_clk = { .name = "slimbus1_slimbus_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT, .clkdm_name = "abe_clkdm", @@ -2240,7 +2279,7 @@ static struct clk slimbus1_slimbus_clk = { static struct clk slimbus1_fck = { .name = "slimbus1_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "abe_clkdm", @@ -2250,7 +2289,7 @@ static struct clk slimbus1_fck = { static struct clk slimbus2_fclk_1 = { .name = "slimbus2_fclk_1", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -2260,7 +2299,7 @@ static struct clk slimbus2_fclk_1 = { static struct clk slimbus2_fclk_0 = { .name = "slimbus2_fclk_0", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -2270,7 +2309,7 @@ static struct clk slimbus2_fclk_0 = { static struct clk slimbus2_slimbus_clk = { .name = "slimbus2_slimbus_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT, .clkdm_name = "l4_per_clkdm", @@ -2280,7 +2319,7 @@ static struct clk slimbus2_slimbus_clk = { static struct clk slimbus2_fck = { .name = "slimbus2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2290,7 +2329,7 @@ static struct clk slimbus2_fck = { static struct clk smartreflex_core_fck = { .name = "smartreflex_core_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_ao_clkdm", @@ -2300,7 +2339,7 @@ static struct clk smartreflex_core_fck = { static struct clk smartreflex_iva_fck = { .name = "smartreflex_iva_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_ao_clkdm", @@ -2310,7 +2349,7 @@ static struct clk smartreflex_iva_fck = { static struct clk smartreflex_mpu_fck = { .name = "smartreflex_mpu_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_ao_clkdm", @@ -2326,7 +2365,7 @@ static struct clk timer1_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2341,7 +2380,7 @@ static struct clk timer10_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2356,7 +2395,7 @@ static struct clk timer11_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2371,7 +2410,7 @@ static struct clk timer2_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2386,7 +2425,7 @@ static struct clk timer3_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2401,7 +2440,7 @@ static struct clk timer4_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2422,7 +2461,7 @@ static struct clk timer5_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2437,7 +2476,7 @@ static struct clk timer6_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2452,7 +2491,7 @@ static struct clk timer7_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2467,7 +2506,7 @@ static struct clk timer8_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2482,7 +2521,7 @@ static struct clk timer9_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, .clksel_mask = OMAP4430_CLKSEL_MASK, - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, @@ -2491,7 +2530,7 @@ static struct clk timer9_fck = { static struct clk uart1_fck = { .name = "uart1_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2501,7 +2540,7 @@ static struct clk uart1_fck = { static struct clk uart2_fck = { .name = "uart2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2511,7 +2550,7 @@ static struct clk uart2_fck = { static struct clk uart3_fck = { .name = "uart3_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2521,7 +2560,7 @@ static struct clk uart3_fck = { static struct clk uart4_fck = { .name = "uart4_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_per_clkdm", @@ -2531,7 +2570,7 @@ static struct clk uart4_fck = { static struct clk usb_host_fs_fck = { .name = "usb_host_fs_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l3_init_clkdm", @@ -2558,7 +2597,7 @@ static struct clk utmi_p1_gfclk = { static struct clk usb_host_hs_utmi_p1_clk = { .name = "usb_host_hs_utmi_p1_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2585,7 +2624,7 @@ static struct clk utmi_p2_gfclk = { static struct clk usb_host_hs_utmi_p2_clk = { .name = "usb_host_hs_utmi_p2_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2595,7 +2634,7 @@ static struct clk usb_host_hs_utmi_p2_clk = { static struct clk usb_host_hs_utmi_p3_clk = { .name = "usb_host_hs_utmi_p3_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2605,7 +2644,7 @@ static struct clk usb_host_hs_utmi_p3_clk = { static struct clk usb_host_hs_hsic480m_p1_clk = { .name = "usb_host_hs_hsic480m_p1_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2615,7 +2654,7 @@ static struct clk usb_host_hs_hsic480m_p1_clk = { static struct clk usb_host_hs_hsic60m_p1_clk = { .name = "usb_host_hs_hsic60m_p1_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2625,7 +2664,7 @@ static struct clk usb_host_hs_hsic60m_p1_clk = { static struct clk usb_host_hs_hsic60m_p2_clk = { .name = "usb_host_hs_hsic60m_p2_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2635,7 +2674,7 @@ static struct clk usb_host_hs_hsic60m_p2_clk = { static struct clk usb_host_hs_hsic480m_p2_clk = { .name = "usb_host_hs_hsic480m_p2_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2645,7 +2684,7 @@ static struct clk usb_host_hs_hsic480m_p2_clk = { static struct clk usb_host_hs_func48mclk = { .name = "usb_host_hs_func48mclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2655,7 +2694,7 @@ static struct clk usb_host_hs_func48mclk = { static struct clk usb_host_hs_fck = { .name = "usb_host_hs_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l3_init_clkdm", @@ -2682,7 +2721,7 @@ static struct clk otg_60m_gfclk = { static struct clk usb_otg_hs_xclk = { .name = "usb_otg_hs_xclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_XCLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2692,7 +2731,7 @@ static struct clk usb_otg_hs_xclk = { static struct clk usb_otg_hs_ick = { .name = "usb_otg_hs_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_init_clkdm", @@ -2702,7 +2741,7 @@ static struct clk usb_otg_hs_ick = { static struct clk usb_phy_cm_clk32k = { .name = "usb_phy_cm_clk32k", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_ALWON_USBPHY_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_CLK32K_SHIFT, .clkdm_name = "l4_ao_clkdm", @@ -2712,7 +2751,7 @@ static struct clk usb_phy_cm_clk32k = { static struct clk usb_tll_hs_usb_ch2_clk = { .name = "usb_tll_hs_usb_ch2_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2722,7 +2761,7 @@ static struct clk usb_tll_hs_usb_ch2_clk = { static struct clk usb_tll_hs_usb_ch0_clk = { .name = "usb_tll_hs_usb_ch0_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2732,7 +2771,7 @@ static struct clk usb_tll_hs_usb_ch0_clk = { static struct clk usb_tll_hs_usb_ch1_clk = { .name = "usb_tll_hs_usb_ch1_clk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT, .clkdm_name = "l3_init_clkdm", @@ -2742,7 +2781,7 @@ static struct clk usb_tll_hs_usb_ch1_clk = { static struct clk usb_tll_hs_ick = { .name = "usb_tll_hs_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l3_init_clkdm", @@ -2751,8 +2790,8 @@ static struct clk usb_tll_hs_ick = { }; static const struct clksel_rate div2_14to18_rates[] = { - { .div = 14, .val = 0, .flags = RATE_IN_4430 }, - { .div = 18, .val = 1, .flags = RATE_IN_4430 }, + { .div = 14, .val = 0, .flags = RATE_IN_44XX }, + { .div = 18, .val = 1, .flags = RATE_IN_44XX }, { .div = 0 }, }; @@ -2775,7 +2814,7 @@ static struct clk usim_ck = { static struct clk usim_fclk = { .name = "usim_fclk", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL, .enable_bit = OMAP4430_OPTFCLKEN_FCLK_SHIFT, .clkdm_name = "l4_wkup_clkdm", @@ -2785,7 +2824,7 @@ static struct clk usim_fclk = { static struct clk usim_fck = { .name = "usim_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_HWCTRL, .clkdm_name = "l4_wkup_clkdm", @@ -2795,7 +2834,7 @@ static struct clk usim_fck = { static struct clk wd_timer2_fck = { .name = "wd_timer2_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "l4_wkup_clkdm", @@ -2805,7 +2844,7 @@ static struct clk wd_timer2_fck = { static struct clk wd_timer3_fck = { .name = "wd_timer3_fck", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap4_dflt_wait, .enable_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL, .enable_bit = OMAP4430_MODULEMODE_SWCTRL, .clkdm_name = "abe_clkdm", @@ -2850,19 +2889,39 @@ static struct clk trace_clk_div_ck = { /* SCRM aux clk nodes */ -static const struct clksel auxclk_sel[] = { +static const struct clksel auxclk_src_sel[] = { { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, { .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates }, { .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates }, { .parent = NULL }, }; -static struct clk auxclk0_ck = { - .name = "auxclk0_ck", +static const struct clksel_rate div16_1to16_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_44XX }, + { .div = 2, .val = 1, .flags = RATE_IN_44XX }, + { .div = 3, .val = 2, .flags = RATE_IN_44XX }, + { .div = 4, .val = 3, .flags = RATE_IN_44XX }, + { .div = 5, .val = 4, .flags = RATE_IN_44XX }, + { .div = 6, .val = 5, .flags = RATE_IN_44XX }, + { .div = 7, .val = 6, .flags = RATE_IN_44XX }, + { .div = 8, .val = 7, .flags = RATE_IN_44XX }, + { .div = 9, .val = 8, .flags = RATE_IN_44XX }, + { .div = 10, .val = 9, .flags = RATE_IN_44XX }, + { .div = 11, .val = 10, .flags = RATE_IN_44XX }, + { .div = 12, .val = 11, .flags = RATE_IN_44XX }, + { .div = 13, .val = 12, .flags = RATE_IN_44XX }, + { .div = 14, .val = 13, .flags = RATE_IN_44XX }, + { .div = 15, .val = 14, .flags = RATE_IN_44XX }, + { .div = 16, .val = 15, .flags = RATE_IN_44XX }, + { .div = 0 }, +}; + +static struct clk auxclk0_src_ck = { + .name = "auxclk0_src_ck", .parent = &sys_clkin_ck, .init = &omap2_init_clksel_parent, - .ops = &clkops_omap2_dflt, - .clksel = auxclk_sel, + .ops = &clkops_omap4_dflt_wait, + .clksel = auxclk_src_sel, .clksel_reg = OMAP4_SCRM_AUXCLK0, .clksel_mask = OMAP4_SRCSELECT_MASK, .recalc = &omap2_clksel_recalc, @@ -2870,12 +2929,29 @@ static struct clk auxclk0_ck = { .enable_bit = OMAP4_ENABLE_SHIFT, }; -static struct clk auxclk1_ck = { - .name = "auxclk1_ck", +static const struct clksel auxclk0_sel[] = { + { .parent = &auxclk0_src_ck, .rates = div16_1to16_rates }, + { .parent = NULL }, +}; + +static struct clk auxclk0_ck = { + .name = "auxclk0_ck", + .parent = &auxclk0_src_ck, + .clksel = auxclk0_sel, + .clksel_reg = OMAP4_SCRM_AUXCLK0, + .clksel_mask = OMAP4_CLKDIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static struct clk auxclk1_src_ck = { + .name = "auxclk1_src_ck", .parent = &sys_clkin_ck, .init = &omap2_init_clksel_parent, - .ops = &clkops_omap2_dflt, - .clksel = auxclk_sel, + .ops = &clkops_omap4_dflt_wait, + .clksel = auxclk_src_sel, .clksel_reg = OMAP4_SCRM_AUXCLK1, .clksel_mask = OMAP4_SRCSELECT_MASK, .recalc = &omap2_clksel_recalc, @@ -2883,24 +2959,59 @@ static struct clk auxclk1_ck = { .enable_bit = OMAP4_ENABLE_SHIFT, }; -static struct clk auxclk2_ck = { - .name = "auxclk2_ck", +static const struct clksel auxclk1_sel[] = { + { .parent = &auxclk1_src_ck, .rates = div16_1to16_rates }, + { .parent = NULL }, +}; + +static struct clk auxclk1_ck = { + .name = "auxclk1_ck", + .parent = &auxclk1_src_ck, + .clksel = auxclk1_sel, + .clksel_reg = OMAP4_SCRM_AUXCLK1, + .clksel_mask = OMAP4_CLKDIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static struct clk auxclk2_src_ck = { + .name = "auxclk2_src_ck", .parent = &sys_clkin_ck, .init = &omap2_init_clksel_parent, - .ops = &clkops_omap2_dflt, - .clksel = auxclk_sel, + .ops = &clkops_omap4_dflt_wait, + .clksel = auxclk_src_sel, .clksel_reg = OMAP4_SCRM_AUXCLK2, .clksel_mask = OMAP4_SRCSELECT_MASK, .recalc = &omap2_clksel_recalc, .enable_reg = OMAP4_SCRM_AUXCLK2, .enable_bit = OMAP4_ENABLE_SHIFT, }; -static struct clk auxclk3_ck = { - .name = "auxclk3_ck", + +static const struct clksel auxclk2_sel[] = { + { .parent = &auxclk2_src_ck, .rates = div16_1to16_rates }, + { .parent = NULL }, +}; + +static struct clk auxclk2_ck = { + .name = "auxclk2_ck", + .parent = &auxclk2_src_ck, + .clksel = auxclk2_sel, + .clksel_reg = OMAP4_SCRM_AUXCLK2, + .clksel_mask = OMAP4_CLKDIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static struct clk auxclk3_src_ck = { + .name = "auxclk3_src_ck", .parent = &sys_clkin_ck, .init = &omap2_init_clksel_parent, - .ops = &clkops_omap2_dflt, - .clksel = auxclk_sel, + .ops = &clkops_omap4_dflt_wait, + .clksel = auxclk_src_sel, .clksel_reg = OMAP4_SCRM_AUXCLK3, .clksel_mask = OMAP4_SRCSELECT_MASK, .recalc = &omap2_clksel_recalc, @@ -2908,12 +3019,29 @@ static struct clk auxclk3_ck = { .enable_bit = OMAP4_ENABLE_SHIFT, }; -static struct clk auxclk4_ck = { - .name = "auxclk4_ck", +static const struct clksel auxclk3_sel[] = { + { .parent = &auxclk3_src_ck, .rates = div16_1to16_rates }, + { .parent = NULL }, +}; + +static struct clk auxclk3_ck = { + .name = "auxclk3_ck", + .parent = &auxclk3_src_ck, + .clksel = auxclk3_sel, + .clksel_reg = OMAP4_SCRM_AUXCLK3, + .clksel_mask = OMAP4_CLKDIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static struct clk auxclk4_src_ck = { + .name = "auxclk4_src_ck", .parent = &sys_clkin_ck, .init = &omap2_init_clksel_parent, - .ops = &clkops_omap2_dflt, - .clksel = auxclk_sel, + .ops = &clkops_omap4_dflt_wait, + .clksel = auxclk_src_sel, .clksel_reg = OMAP4_SCRM_AUXCLK4, .clksel_mask = OMAP4_SRCSELECT_MASK, .recalc = &omap2_clksel_recalc, @@ -2921,12 +3049,29 @@ static struct clk auxclk4_ck = { .enable_bit = OMAP4_ENABLE_SHIFT, }; -static struct clk auxclk5_ck = { - .name = "auxclk5_ck", +static const struct clksel auxclk4_sel[] = { + { .parent = &auxclk4_src_ck, .rates = div16_1to16_rates }, + { .parent = NULL }, +}; + +static struct clk auxclk4_ck = { + .name = "auxclk4_ck", + .parent = &auxclk4_src_ck, + .clksel = auxclk4_sel, + .clksel_reg = OMAP4_SCRM_AUXCLK4, + .clksel_mask = OMAP4_CLKDIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + +static struct clk auxclk5_src_ck = { + .name = "auxclk5_src_ck", .parent = &sys_clkin_ck, .init = &omap2_init_clksel_parent, - .ops = &clkops_omap2_dflt, - .clksel = auxclk_sel, + .ops = &clkops_omap4_dflt_wait, + .clksel = auxclk_src_sel, .clksel_reg = OMAP4_SCRM_AUXCLK5, .clksel_mask = OMAP4_SRCSELECT_MASK, .recalc = &omap2_clksel_recalc, @@ -2934,6 +3079,23 @@ static struct clk auxclk5_ck = { .enable_bit = OMAP4_ENABLE_SHIFT, }; +static const struct clksel auxclk5_sel[] = { + { .parent = &auxclk5_src_ck, .rates = div16_1to16_rates }, + { .parent = NULL }, +}; + +static struct clk auxclk5_ck = { + .name = "auxclk5_ck", + .parent = &auxclk5_src_ck, + .clksel = auxclk5_sel, + .clksel_reg = OMAP4_SCRM_AUXCLK5, + .clksel_mask = OMAP4_CLKDIV_MASK, + .ops = &clkops_null, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate, +}; + static const struct clksel auxclkreq_sel[] = { { .parent = &auxclk0_ck, .rates = div_1_0_rates }, { .parent = &auxclk1_ck, .rates = div_1_1_rates }, @@ -3010,289 +3172,411 @@ static struct clk auxclkreq5_ck = { .recalc = &omap2_clksel_recalc, }; +static struct clk smp_twd = { + .name = "smp_twd", + .parent = &dpll_mpu_ck, + .ops = &clkops_null, + .fixed_div = 2, + .recalc = &omap_fixed_divisor_recalc, +}; + /* * clkdev */ static struct omap_clk omap44xx_clks[] = { - CLK(NULL, "extalt_clkin_ck", &extalt_clkin_ck, CK_443X), - CLK(NULL, "pad_clks_ck", &pad_clks_ck, CK_443X), - CLK(NULL, "pad_slimbus_core_clks_ck", &pad_slimbus_core_clks_ck, CK_443X), - CLK(NULL, "secure_32k_clk_src_ck", &secure_32k_clk_src_ck, CK_443X), - CLK(NULL, "slimbus_clk", &slimbus_clk, CK_443X), - CLK(NULL, "sys_32k_ck", &sys_32k_ck, CK_443X), - CLK(NULL, "virt_12000000_ck", &virt_12000000_ck, CK_443X), - CLK(NULL, "virt_13000000_ck", &virt_13000000_ck, CK_443X), - CLK(NULL, "virt_16800000_ck", &virt_16800000_ck, CK_443X), - CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_443X), - CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_443X), - CLK(NULL, "virt_27000000_ck", &virt_27000000_ck, CK_443X), - CLK(NULL, "virt_38400000_ck", &virt_38400000_ck, CK_443X), - CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_443X), - CLK(NULL, "tie_low_clock_ck", &tie_low_clock_ck, CK_443X), - CLK(NULL, "utmi_phy_clkout_ck", &utmi_phy_clkout_ck, CK_443X), - CLK(NULL, "xclk60mhsp1_ck", &xclk60mhsp1_ck, CK_443X), - CLK(NULL, "xclk60mhsp2_ck", &xclk60mhsp2_ck, CK_443X), - CLK(NULL, "xclk60motg_ck", &xclk60motg_ck, CK_443X), - CLK(NULL, "abe_dpll_bypass_clk_mux_ck", &abe_dpll_bypass_clk_mux_ck, CK_443X), - CLK(NULL, "abe_dpll_refclk_mux_ck", &abe_dpll_refclk_mux_ck, CK_443X), - CLK(NULL, "dpll_abe_ck", &dpll_abe_ck, CK_443X), - CLK(NULL, "dpll_abe_x2_ck", &dpll_abe_x2_ck, CK_443X), - CLK(NULL, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, CK_443X), - CLK(NULL, "abe_24m_fclk", &abe_24m_fclk, CK_443X), - CLK(NULL, "abe_clk", &abe_clk, CK_443X), - CLK(NULL, "aess_fclk", &aess_fclk, CK_443X), - CLK(NULL, "dpll_abe_m3x2_ck", &dpll_abe_m3x2_ck, CK_443X), - CLK(NULL, "core_hsd_byp_clk_mux_ck", &core_hsd_byp_clk_mux_ck, CK_443X), - CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_443X), - CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_443X), - CLK(NULL, "dpll_core_m6x2_ck", &dpll_core_m6x2_ck, CK_443X), - CLK(NULL, "dbgclk_mux_ck", &dbgclk_mux_ck, CK_443X), - CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_443X), - CLK(NULL, "ddrphy_ck", &ddrphy_ck, CK_443X), - CLK(NULL, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, CK_443X), - CLK(NULL, "div_core_ck", &div_core_ck, CK_443X), - CLK(NULL, "div_iva_hs_clk", &div_iva_hs_clk, CK_443X), - CLK(NULL, "div_mpu_hs_clk", &div_mpu_hs_clk, CK_443X), - CLK(NULL, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck, CK_443X), - CLK(NULL, "dll_clk_div_ck", &dll_clk_div_ck, CK_443X), - CLK(NULL, "dpll_abe_m2_ck", &dpll_abe_m2_ck, CK_443X), - CLK(NULL, "dpll_core_m3x2_ck", &dpll_core_m3x2_ck, CK_443X), - CLK(NULL, "dpll_core_m7x2_ck", &dpll_core_m7x2_ck, CK_443X), - CLK(NULL, "iva_hsd_byp_clk_mux_ck", &iva_hsd_byp_clk_mux_ck, CK_443X), - CLK(NULL, "dpll_iva_ck", &dpll_iva_ck, CK_443X), - CLK(NULL, "dpll_iva_x2_ck", &dpll_iva_x2_ck, CK_443X), - CLK(NULL, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, CK_443X), - CLK(NULL, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, CK_443X), - CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X), - CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X), - CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_443X), - CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_443X), - CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_443X), - CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_443X), - CLK(NULL, "dpll_per_x2_ck", &dpll_per_x2_ck, CK_443X), - CLK(NULL, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, CK_443X), - CLK(NULL, "dpll_per_m3x2_ck", &dpll_per_m3x2_ck, CK_443X), - CLK(NULL, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, CK_443X), - CLK(NULL, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, CK_443X), - CLK(NULL, "dpll_per_m6x2_ck", &dpll_per_m6x2_ck, CK_443X), - CLK(NULL, "dpll_per_m7x2_ck", &dpll_per_m7x2_ck, CK_443X), - CLK(NULL, "dpll_unipro_ck", &dpll_unipro_ck, CK_443X), - CLK(NULL, "dpll_unipro_x2_ck", &dpll_unipro_x2_ck, CK_443X), - CLK(NULL, "dpll_unipro_m2x2_ck", &dpll_unipro_m2x2_ck, CK_443X), - CLK(NULL, "usb_hs_clk_div_ck", &usb_hs_clk_div_ck, CK_443X), - CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_443X), - CLK(NULL, "dpll_usb_clkdcoldo_ck", &dpll_usb_clkdcoldo_ck, CK_443X), - CLK(NULL, "dpll_usb_m2_ck", &dpll_usb_m2_ck, CK_443X), - CLK(NULL, "ducati_clk_mux_ck", &ducati_clk_mux_ck, CK_443X), - CLK(NULL, "func_12m_fclk", &func_12m_fclk, CK_443X), - CLK(NULL, "func_24m_clk", &func_24m_clk, CK_443X), - CLK(NULL, "func_24mc_fclk", &func_24mc_fclk, CK_443X), - CLK(NULL, "func_48m_fclk", &func_48m_fclk, CK_443X), - CLK(NULL, "func_48mc_fclk", &func_48mc_fclk, CK_443X), - CLK(NULL, "func_64m_fclk", &func_64m_fclk, CK_443X), - CLK(NULL, "func_96m_fclk", &func_96m_fclk, CK_443X), - CLK(NULL, "hsmmc6_fclk", &hsmmc6_fclk, CK_443X), - CLK(NULL, "init_60m_fclk", &init_60m_fclk, CK_443X), - CLK(NULL, "l3_div_ck", &l3_div_ck, CK_443X), - CLK(NULL, "l4_div_ck", &l4_div_ck, CK_443X), - CLK(NULL, "lp_clk_div_ck", &lp_clk_div_ck, CK_443X), - CLK(NULL, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, CK_443X), - CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_443X), - CLK(NULL, "mcasp2_fclk", &mcasp2_fclk, CK_443X), - CLK(NULL, "mcasp3_fclk", &mcasp3_fclk, CK_443X), - CLK(NULL, "ocp_abe_iclk", &ocp_abe_iclk, CK_443X), - CLK(NULL, "per_abe_24m_fclk", &per_abe_24m_fclk, CK_443X), - CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_443X), - CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_443X), - CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_443X), - CLK(NULL, "aes1_fck", &aes1_fck, CK_443X), - CLK(NULL, "aes2_fck", &aes2_fck, CK_443X), - CLK(NULL, "aess_fck", &aess_fck, CK_443X), + CLK(NULL, "extalt_clkin_ck", &extalt_clkin_ck, CK_44XX), + CLK(NULL, "pad_clks_ck", &pad_clks_ck, CK_44XX), + CLK(NULL, "pad_slimbus_core_clks_ck", &pad_slimbus_core_clks_ck, CK_44XX), + CLK(NULL, "secure_32k_clk_src_ck", &secure_32k_clk_src_ck, CK_44XX), + CLK(NULL, "slimbus_clk", &slimbus_clk, CK_44XX), + CLK(NULL, "sys_32k_ck", &sys_32k_ck, CK_44XX), + CLK(NULL, "virt_12000000_ck", &virt_12000000_ck, CK_44XX), + CLK(NULL, "virt_13000000_ck", &virt_13000000_ck, CK_44XX), + CLK(NULL, "virt_16800000_ck", &virt_16800000_ck, CK_44XX), + CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_44XX), + CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_44XX), + CLK(NULL, "virt_27000000_ck", &virt_27000000_ck, CK_44XX), + CLK(NULL, "virt_38400000_ck", &virt_38400000_ck, CK_44XX), + CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_44XX), + CLK(NULL, "tie_low_clock_ck", &tie_low_clock_ck, CK_44XX), + CLK(NULL, "utmi_phy_clkout_ck", &utmi_phy_clkout_ck, CK_44XX), + CLK(NULL, "xclk60mhsp1_ck", &xclk60mhsp1_ck, CK_44XX), + CLK(NULL, "xclk60mhsp2_ck", &xclk60mhsp2_ck, CK_44XX), + CLK(NULL, "xclk60motg_ck", &xclk60motg_ck, CK_44XX), + CLK(NULL, "abe_dpll_bypass_clk_mux_ck", &abe_dpll_bypass_clk_mux_ck, CK_44XX), + CLK(NULL, "abe_dpll_refclk_mux_ck", &abe_dpll_refclk_mux_ck, CK_44XX), + CLK(NULL, "dpll_abe_ck", &dpll_abe_ck, CK_44XX), + CLK(NULL, "dpll_abe_x2_ck", &dpll_abe_x2_ck, CK_44XX), + CLK(NULL, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, CK_44XX), + CLK(NULL, "abe_24m_fclk", &abe_24m_fclk, CK_44XX), + CLK(NULL, "abe_clk", &abe_clk, CK_44XX), + CLK(NULL, "aess_fclk", &aess_fclk, CK_44XX), + CLK(NULL, "dpll_abe_m3x2_ck", &dpll_abe_m3x2_ck, CK_44XX), + CLK(NULL, "core_hsd_byp_clk_mux_ck", &core_hsd_byp_clk_mux_ck, CK_44XX), + CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_44XX), + CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_44XX), + CLK(NULL, "dpll_core_m6x2_ck", &dpll_core_m6x2_ck, CK_44XX), + CLK(NULL, "dbgclk_mux_ck", &dbgclk_mux_ck, CK_44XX), + CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_44XX), + CLK(NULL, "ddrphy_ck", &ddrphy_ck, CK_44XX), + CLK(NULL, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, CK_44XX), + CLK(NULL, "virt_l3_ck", &virt_l3_ck, CK_44XX), + CLK(NULL, "div_core_ck", &div_core_ck, CK_44XX), + CLK(NULL, "div_iva_hs_clk", &div_iva_hs_clk, CK_44XX), + CLK(NULL, "div_mpu_hs_clk", &div_mpu_hs_clk, CK_44XX), + CLK(NULL, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck, CK_44XX), + CLK(NULL, "dll_clk_div_ck", &dll_clk_div_ck, CK_44XX), + CLK(NULL, "dpll_abe_m2_ck", &dpll_abe_m2_ck, CK_44XX), + CLK(NULL, "dpll_core_m3x2_ck", &dpll_core_m3x2_ck, CK_44XX), + CLK(NULL, "dpll_core_m7x2_ck", &dpll_core_m7x2_ck, CK_44XX), + CLK(NULL, "iva_hsd_byp_clk_mux_ck", &iva_hsd_byp_clk_mux_ck, CK_44XX), + CLK(NULL, "dpll_iva_ck", &dpll_iva_ck, CK_44XX), + CLK(NULL, "dpll_iva_x2_ck", &dpll_iva_x2_ck, CK_44XX), + CLK(NULL, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, CK_44XX), + CLK(NULL, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, CK_44XX), + CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_44XX), + CLK(NULL, "virt_dpll_mpu_ck", &virt_dpll_mpu_ck, CK_446X), + CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_44XX), + CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_44XX), + CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_44XX), + CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_44XX), + CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_44XX), + CLK(NULL, "dpll_per_x2_ck", &dpll_per_x2_ck, CK_44XX), + CLK(NULL, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, CK_44XX), + CLK(NULL, "dpll_per_m3x2_ck", &dpll_per_m3x2_ck, CK_44XX), + CLK(NULL, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, CK_44XX), + CLK(NULL, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, CK_44XX), + CLK(NULL, "dpll_per_m6x2_ck", &dpll_per_m6x2_ck, CK_44XX), + CLK(NULL, "dpll_per_m7x2_ck", &dpll_per_m7x2_ck, CK_44XX), + CLK(NULL, "dpll_unipro_ck", &dpll_unipro_ck, CK_44XX), + CLK(NULL, "dpll_unipro_x2_ck", &dpll_unipro_x2_ck, CK_44XX), + CLK(NULL, "dpll_unipro_m2x2_ck", &dpll_unipro_m2x2_ck, CK_44XX), + CLK(NULL, "usb_hs_clk_div_ck", &usb_hs_clk_div_ck, CK_44XX), + CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_44XX), + CLK(NULL, "dpll_usb_clkdcoldo_ck", &dpll_usb_clkdcoldo_ck, CK_44XX), + CLK(NULL, "dpll_usb_m2_ck", &dpll_usb_m2_ck, CK_44XX), + CLK(NULL, "ducati_clk_mux_ck", &ducati_clk_mux_ck, CK_44XX), + CLK(NULL, "func_12m_fclk", &func_12m_fclk, CK_44XX), + CLK(NULL, "func_24m_clk", &func_24m_clk, CK_44XX), + CLK(NULL, "func_24mc_fclk", &func_24mc_fclk, CK_44XX), + CLK(NULL, "func_48m_fclk", &func_48m_fclk, CK_44XX), + CLK(NULL, "func_48mc_fclk", &func_48mc_fclk, CK_44XX), + CLK(NULL, "func_64m_fclk", &func_64m_fclk, CK_44XX), + CLK(NULL, "func_96m_fclk", &func_96m_fclk, CK_44XX), + CLK(NULL, "hsmmc6_fclk", &hsmmc6_fclk, CK_44XX), + CLK(NULL, "init_60m_fclk", &init_60m_fclk, CK_44XX), + CLK(NULL, "l3_div_ck", &l3_div_ck, CK_44XX), + CLK(NULL, "l4_div_ck", &l4_div_ck, CK_44XX), + CLK(NULL, "lp_clk_div_ck", &lp_clk_div_ck, CK_44XX), + CLK(NULL, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, CK_44XX), + CLK(NULL, "div_ts_ck", &div_ts_ck, CK_446X), + CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_44XX), + CLK(NULL, "mcasp2_fclk", &mcasp2_fclk, CK_44XX), + CLK(NULL, "mcasp3_fclk", &mcasp3_fclk, CK_44XX), + CLK(NULL, "ocp_abe_iclk", &ocp_abe_iclk, CK_44XX), + CLK(NULL, "per_abe_24m_fclk", &per_abe_24m_fclk, CK_44XX), + CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_44XX), + CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_44XX), + CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_44XX), + CLK(NULL, "aes1_fck", &aes1_fck, CK_44XX), + CLK(NULL, "aes2_fck", &aes2_fck, CK_44XX), + CLK(NULL, "aess_fck", &aess_fck, CK_44XX), CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X), - CLK(NULL, "des3des_fck", &des3des_fck, CK_443X), - CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X), - CLK(NULL, "dmic_fck", &dmic_fck, CK_443X), - CLK(NULL, "dsp_fck", &dsp_fck, CK_443X), - CLK(NULL, "sys_clk", &dss_sys_clk, CK_443X), - CLK(NULL, "tv_clk", &dss_tv_clk, CK_443X), - CLK(NULL, "video_clk", &dss_48mhz_clk, CK_443X), - CLK(NULL, "fck", &dss_dss_clk, CK_443X), - CLK(NULL, "ick", &dss_fck, CK_443X), - CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X), - CLK(NULL, "emif1_fck", &emif1_fck, CK_443X), - CLK(NULL, "emif2_fck", &emif2_fck, CK_443X), - CLK(NULL, "fdif_fck", &fdif_fck, CK_443X), - CLK(NULL, "fpka_fck", &fpka_fck, CK_443X), - CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_443X), - CLK(NULL, "gpio1_ick", &gpio1_ick, CK_443X), - CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_443X), - CLK(NULL, "gpio2_ick", &gpio2_ick, CK_443X), - CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_443X), - CLK(NULL, "gpio3_ick", &gpio3_ick, CK_443X), - CLK(NULL, "gpio4_dbclk", &gpio4_dbclk, CK_443X), - CLK(NULL, "gpio4_ick", &gpio4_ick, CK_443X), - CLK(NULL, "gpio5_dbclk", &gpio5_dbclk, CK_443X), - CLK(NULL, "gpio5_ick", &gpio5_ick, CK_443X), - CLK(NULL, "gpio6_dbclk", &gpio6_dbclk, CK_443X), - CLK(NULL, "gpio6_ick", &gpio6_ick, CK_443X), - CLK(NULL, "gpmc_ick", &gpmc_ick, CK_443X), - CLK(NULL, "gpu_fck", &gpu_fck, CK_443X), - CLK("omap2_hdq.0", "fck", &hdq1w_fck, CK_443X), - CLK(NULL, "hsi_fck", &hsi_fck, CK_443X), - CLK("omap_i2c.1", "fck", &i2c1_fck, CK_443X), - CLK("omap_i2c.2", "fck", &i2c2_fck, CK_443X), - CLK("omap_i2c.3", "fck", &i2c3_fck, CK_443X), - CLK("omap_i2c.4", "fck", &i2c4_fck, CK_443X), - CLK(NULL, "ipu_fck", &ipu_fck, CK_443X), - CLK(NULL, "iss_ctrlclk", &iss_ctrlclk, CK_443X), - CLK(NULL, "iss_fck", &iss_fck, CK_443X), - CLK(NULL, "iva_fck", &iva_fck, CK_443X), - CLK(NULL, "kbd_fck", &kbd_fck, CK_443X), - CLK(NULL, "l3_instr_ick", &l3_instr_ick, CK_443X), - CLK(NULL, "l3_main_3_ick", &l3_main_3_ick, CK_443X), - CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_443X), - CLK(NULL, "mcasp_fck", &mcasp_fck, CK_443X), - CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_443X), - CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_443X), - CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_443X), - CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_443X), - CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_443X), - CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_443X), - CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_443X), - CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_443X), - CLK(NULL, "mcpdm_fck", &mcpdm_fck, CK_443X), - CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_443X), - CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_443X), - CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_443X), - CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_443X), - CLK("omap_hsmmc.0", "fck", &mmc1_fck, CK_443X), - CLK("omap_hsmmc.1", "fck", &mmc2_fck, CK_443X), - CLK("omap_hsmmc.2", "fck", &mmc3_fck, CK_443X), - CLK("omap_hsmmc.3", "fck", &mmc4_fck, CK_443X), - CLK("omap_hsmmc.4", "fck", &mmc5_fck, CK_443X), - CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X), - CLK(NULL, "ocp2scp_usb_phy_ick", &ocp2scp_usb_phy_ick, CK_443X), - CLK(NULL, "ocp_wp_noc_ick", &ocp_wp_noc_ick, CK_443X), - CLK("omap_rng", "ick", &rng_ick, CK_443X), - CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_443X), - CLK(NULL, "sl2if_ick", &sl2if_ick, CK_443X), - CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_443X), - CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_443X), - CLK(NULL, "slimbus1_fclk_2", &slimbus1_fclk_2, CK_443X), - CLK(NULL, "slimbus1_slimbus_clk", &slimbus1_slimbus_clk, CK_443X), - CLK(NULL, "slimbus1_fck", &slimbus1_fck, CK_443X), - CLK(NULL, "slimbus2_fclk_1", &slimbus2_fclk_1, CK_443X), - CLK(NULL, "slimbus2_fclk_0", &slimbus2_fclk_0, CK_443X), - CLK(NULL, "slimbus2_slimbus_clk", &slimbus2_slimbus_clk, CK_443X), - CLK(NULL, "slimbus2_fck", &slimbus2_fck, CK_443X), - CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_443X), - CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_443X), - CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_443X), - CLK(NULL, "gpt1_fck", &timer1_fck, CK_443X), - CLK(NULL, "gpt10_fck", &timer10_fck, CK_443X), - CLK(NULL, "gpt11_fck", &timer11_fck, CK_443X), - CLK(NULL, "gpt2_fck", &timer2_fck, CK_443X), - CLK(NULL, "gpt3_fck", &timer3_fck, CK_443X), - CLK(NULL, "gpt4_fck", &timer4_fck, CK_443X), - CLK(NULL, "gpt5_fck", &timer5_fck, CK_443X), - CLK(NULL, "gpt6_fck", &timer6_fck, CK_443X), - CLK(NULL, "gpt7_fck", &timer7_fck, CK_443X), - CLK(NULL, "gpt8_fck", &timer8_fck, CK_443X), - CLK(NULL, "gpt9_fck", &timer9_fck, CK_443X), - CLK(NULL, "uart1_fck", &uart1_fck, CK_443X), - CLK(NULL, "uart2_fck", &uart2_fck, CK_443X), - CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), - CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), - CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X), - CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X), - CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X), - CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X), - CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X), - CLK(NULL, "usb_host_hs_utmi_p2_clk", &usb_host_hs_utmi_p2_clk, CK_443X), - CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_443X), - CLK(NULL, "usb_host_hs_hsic480m_p1_clk", &usb_host_hs_hsic480m_p1_clk, CK_443X), - CLK(NULL, "usb_host_hs_hsic60m_p1_clk", &usb_host_hs_hsic60m_p1_clk, CK_443X), - CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X), - CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X), - CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X), - CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X), - CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X), - CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X), - CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X), - CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X), - CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X), - CLK(NULL, "usb_phy_cm_clk32k", &usb_phy_cm_clk32k, CK_443X), - CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_443X), - CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X), - CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X), - CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X), - CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X), - CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X), - CLK(NULL, "usim_ck", &usim_ck, CK_443X), - CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), - CLK(NULL, "usim_fck", &usim_fck, CK_443X), - CLK("omap_wdt", "fck", &wd_timer2_fck, CK_443X), - CLK(NULL, "mailboxes_ick", &dummy_ck, CK_443X), - CLK(NULL, "wd_timer3_fck", &wd_timer3_fck, CK_443X), - CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_443X), - CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck, CK_443X), - CLK(NULL, "gpmc_ck", &dummy_ck, CK_443X), - CLK(NULL, "gpt1_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt2_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt3_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt4_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt5_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt6_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt7_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt8_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt9_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt10_ick", &dummy_ck, CK_443X), - CLK(NULL, "gpt11_ick", &dummy_ck, CK_443X), - CLK("omap_i2c.1", "ick", &dummy_ck, CK_443X), - CLK("omap_i2c.2", "ick", &dummy_ck, CK_443X), - CLK("omap_i2c.3", "ick", &dummy_ck, CK_443X), - CLK("omap_i2c.4", "ick", &dummy_ck, CK_443X), - CLK("omap_hsmmc.0", "ick", &dummy_ck, CK_443X), - CLK("omap_hsmmc.1", "ick", &dummy_ck, CK_443X), - CLK("omap_hsmmc.2", "ick", &dummy_ck, CK_443X), - CLK("omap_hsmmc.3", "ick", &dummy_ck, CK_443X), - CLK("omap_hsmmc.4", "ick", &dummy_ck, CK_443X), - CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_443X), - CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_443X), - CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_443X), - CLK("omap-mcbsp.4", "ick", &dummy_ck, CK_443X), - CLK("omap2_mcspi.1", "ick", &dummy_ck, CK_443X), - CLK("omap2_mcspi.2", "ick", &dummy_ck, CK_443X), - CLK("omap2_mcspi.3", "ick", &dummy_ck, CK_443X), - CLK("omap2_mcspi.4", "ick", &dummy_ck, CK_443X), - CLK(NULL, "uart1_ick", &dummy_ck, CK_443X), - CLK(NULL, "uart2_ick", &dummy_ck, CK_443X), - CLK(NULL, "uart3_ick", &dummy_ck, CK_443X), - CLK(NULL, "uart4_ick", &dummy_ck, CK_443X), - CLK("omap_wdt", "ick", &dummy_ck, CK_443X), - CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X), - CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X), - CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X), - CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X), - CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X), - CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X), - CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_443X), - CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_443X), - CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_443X), - CLK(NULL, "auxclkreq3_ck", &auxclkreq3_ck, CK_443X), - CLK(NULL, "auxclkreq4_ck", &auxclkreq4_ck, CK_443X), - CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X), -}; + CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X), + CLK(NULL, "des3des_fck", &des3des_fck, CK_44XX), + CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_44XX), + CLK(NULL, "dmic_fck", &dmic_fck, CK_44XX), + CLK(NULL, "dsp_fck", &dsp_fck, CK_44XX), + CLK(NULL, "sys_clk", &dss_sys_clk, CK_44XX), + CLK(NULL, "tv_clk", &dss_tv_clk, CK_44XX), + CLK(NULL, "video_clk", &dss_48mhz_clk, CK_44XX), + CLK(NULL, "fck", &dss_dss_clk, CK_44XX), + CLK(NULL, "ick", &dss_fck, CK_44XX), + CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_44XX), + CLK(NULL, "emif1_fck", &emif1_fck, CK_44XX), + CLK(NULL, "emif2_fck", &emif2_fck, CK_44XX), + CLK(NULL, "fdif_fck", &fdif_fck, CK_44XX), + CLK(NULL, "fpka_fck", &fpka_fck, CK_44XX), + CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_44XX), + CLK(NULL, "gpio1_ick", &gpio1_ick, CK_44XX), + CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_44XX), + CLK(NULL, "gpio2_ick", &gpio2_ick, CK_44XX), + CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_44XX), + CLK(NULL, "gpio3_ick", &gpio3_ick, CK_44XX), + CLK(NULL, "gpio4_dbclk", &gpio4_dbclk, CK_44XX), + CLK(NULL, "gpio4_ick", &gpio4_ick, CK_44XX), + CLK(NULL, "gpio5_dbclk", &gpio5_dbclk, CK_44XX), + CLK(NULL, "gpio5_ick", &gpio5_ick, CK_44XX), + CLK(NULL, "gpio6_dbclk", &gpio6_dbclk, CK_44XX), + CLK(NULL, "gpio6_ick", &gpio6_ick, CK_44XX), + CLK(NULL, "gpmc_ick", &gpmc_ick, CK_44XX), + CLK(NULL, "gpu_fck", &gpu_fck, CK_44XX), + CLK("omap2_hdq.0", "fck", &hdq1w_fck, CK_44XX), + CLK(NULL, "hsi_fck", &hsi_fck, CK_44XX), + CLK("omap_i2c.1", "fck", &i2c1_fck, CK_44XX), + CLK("omap_i2c.2", "fck", &i2c2_fck, CK_44XX), + CLK("omap_i2c.3", "fck", &i2c3_fck, CK_44XX), + CLK("omap_i2c.4", "fck", &i2c4_fck, CK_44XX), + CLK(NULL, "ipu_fck", &ipu_fck, CK_44XX), + CLK(NULL, "iss_ctrlclk", &iss_ctrlclk, CK_44XX), + CLK(NULL, "iss_fck", &iss_fck, CK_44XX), + CLK(NULL, "iva_fck", &iva_fck, CK_44XX), + CLK(NULL, "kbd_fck", &kbd_fck, CK_44XX), + CLK(NULL, "l3_instr_ick", &l3_instr_ick, CK_44XX), + CLK(NULL, "l3_main_3_ick", &l3_main_3_ick, CK_44XX), + CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_44XX), + CLK(NULL, "mcasp_fck", &mcasp_fck, CK_44XX), + CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_44XX), + CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_44XX), + CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_44XX), + CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_44XX), + CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_44XX), + CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_44XX), + CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_44XX), + CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_44XX), + CLK(NULL, "mcpdm_fck", &mcpdm_fck, CK_44XX), + CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_44XX), + CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_44XX), + CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_44XX), + CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_44XX), + CLK("omap_hsmmc.0", "fck", &mmc1_fck, CK_44XX), + CLK("omap_hsmmc.1", "fck", &mmc2_fck, CK_44XX), + CLK("omap_hsmmc.2", "fck", &mmc3_fck, CK_44XX), + CLK("omap_hsmmc.3", "fck", &mmc4_fck, CK_44XX), + CLK("omap_hsmmc.4", "fck", &mmc5_fck, CK_44XX), + CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_44XX), + CLK(NULL, "ocp2scp_usb_phy_ick", &ocp2scp_usb_phy_ick, CK_44XX), + CLK(NULL, "ocp_wp_noc_ick", &ocp_wp_noc_ick, CK_44XX), + CLK("omap_rng", "ick", &rng_ick, CK_44XX), + CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_44XX), + CLK(NULL, "sl2if_ick", &sl2if_ick, CK_44XX), + CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_44XX), + CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_44XX), + CLK(NULL, "slimbus1_fclk_2", &slimbus1_fclk_2, CK_44XX), + CLK(NULL, "slimbus1_slimbus_clk", &slimbus1_slimbus_clk, CK_44XX), + CLK(NULL, "slimbus1_fck", &slimbus1_fck, CK_44XX), + CLK(NULL, "slimbus2_fclk_1", &slimbus2_fclk_1, CK_44XX), + CLK(NULL, "slimbus2_fclk_0", &slimbus2_fclk_0, CK_44XX), + CLK(NULL, "slimbus2_slimbus_clk", &slimbus2_slimbus_clk, CK_44XX), + CLK(NULL, "slimbus2_fck", &slimbus2_fck, CK_44XX), + CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_44XX), + CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_44XX), + CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_44XX), + CLK(NULL, "gpt1_fck", &timer1_fck, CK_44XX), + CLK(NULL, "gpt10_fck", &timer10_fck, CK_44XX), + CLK(NULL, "gpt11_fck", &timer11_fck, CK_44XX), + CLK(NULL, "gpt2_fck", &timer2_fck, CK_44XX), + CLK(NULL, "gpt3_fck", &timer3_fck, CK_44XX), + CLK(NULL, "gpt4_fck", &timer4_fck, CK_44XX), + CLK(NULL, "gpt5_fck", &timer5_fck, CK_44XX), + CLK(NULL, "gpt6_fck", &timer6_fck, CK_44XX), + CLK(NULL, "gpt7_fck", &timer7_fck, CK_44XX), + CLK(NULL, "gpt8_fck", &timer8_fck, CK_44XX), + CLK(NULL, "gpt9_fck", &timer9_fck, CK_44XX), + CLK(NULL, "uart1_fck", &uart1_fck, CK_44XX), + CLK(NULL, "uart2_fck", &uart2_fck, CK_44XX), + CLK(NULL, "uart3_fck", &uart3_fck, CK_44XX), + CLK(NULL, "uart4_fck", &uart4_fck, CK_44XX), + CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_44XX), + CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_44XX), + CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_44XX), + CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_44XX), + CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_44XX), + CLK(NULL, "usb_host_hs_utmi_p2_clk", &usb_host_hs_utmi_p2_clk, CK_44XX), + CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_44XX), + CLK(NULL, "usb_host_hs_hsic480m_p1_clk", &usb_host_hs_hsic480m_p1_clk, CK_44XX), + CLK(NULL, "usb_host_hs_hsic60m_p1_clk", &usb_host_hs_hsic60m_p1_clk, CK_44XX), + CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_44XX), + CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_44XX), + CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_44XX), + CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_44XX), + CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_44XX), + CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_44XX), + CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_44XX), + CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_44XX), + CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_44XX), + CLK(NULL, "usb_phy_cm_clk32k", &usb_phy_cm_clk32k, CK_44XX), + CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_44XX), + CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_44XX), + CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_44XX), + CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_44XX), + CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_44XX), + CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_44XX), + CLK(NULL, "usim_ck", &usim_ck, CK_44XX), + CLK(NULL, "usim_fclk", &usim_fclk, CK_44XX), + CLK(NULL, "usim_fck", &usim_fck, CK_44XX), + CLK("omap_wdt", "fck", &wd_timer2_fck, CK_44XX), + CLK(NULL, "mailboxes_ick", &dummy_ck, CK_44XX), + CLK(NULL, "wd_timer3_fck", &wd_timer3_fck, CK_44XX), + CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_44XX), + CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck, CK_44XX), + CLK(NULL, "gpmc_ck", &dummy_ck, CK_44XX), + CLK(NULL, "gpt1_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt2_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt3_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt4_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt5_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt6_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt7_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt8_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt9_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt10_ick", &dummy_ck, CK_44XX), + CLK(NULL, "gpt11_ick", &dummy_ck, CK_44XX), + CLK("omap_i2c.1", "ick", &dummy_ck, CK_44XX), + CLK("omap_i2c.2", "ick", &dummy_ck, CK_44XX), + CLK("omap_i2c.3", "ick", &dummy_ck, CK_44XX), + CLK("omap_i2c.4", "ick", &dummy_ck, CK_44XX), + CLK("omap_hsmmc.0", "ick", &dummy_ck, CK_44XX), + CLK("omap_hsmmc.1", "ick", &dummy_ck, CK_44XX), + CLK("omap_hsmmc.2", "ick", &dummy_ck, CK_44XX), + CLK("omap_hsmmc.3", "ick", &dummy_ck, CK_44XX), + CLK("omap_hsmmc.4", "ick", &dummy_ck, CK_44XX), + CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_44XX), + CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_44XX), + CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_44XX), + CLK("omap-mcbsp.4", "ick", &dummy_ck, CK_44XX), + CLK("omap2_mcspi.1", "ick", &dummy_ck, CK_44XX), + CLK("omap2_mcspi.2", "ick", &dummy_ck, CK_44XX), + CLK("omap2_mcspi.3", "ick", &dummy_ck, CK_44XX), + CLK("omap2_mcspi.4", "ick", &dummy_ck, CK_44XX), + CLK(NULL, "uart1_ick", &dummy_ck, CK_44XX), + CLK(NULL, "uart2_ick", &dummy_ck, CK_44XX), + CLK(NULL, "uart3_ick", &dummy_ck, CK_44XX), + CLK(NULL, "uart4_ick", &dummy_ck, CK_44XX), + CLK("omap_wdt", "ick", &dummy_ck, CK_44XX), + CLK(NULL, "auxclk0_src_ck", &auxclk0_src_ck, CK_44XX), + CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_44XX), + CLK(NULL, "auxclk1_src_ck", &auxclk1_src_ck, CK_44XX), + CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_44XX), + CLK(NULL, "auxclk2_src_ck", &auxclk2_src_ck, CK_44XX), + CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_44XX), + CLK(NULL, "auxclk3_src_ck", &auxclk3_src_ck, CK_44XX), + CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_44XX), + CLK(NULL, "auxclk4_src_ck", &auxclk4_src_ck, CK_44XX), + CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_44XX), + CLK(NULL, "auxclk5_src_ck", &auxclk5_src_ck, CK_44XX), + CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_44XX), + CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_44XX), + CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_44XX), + CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_44XX), + CLK(NULL, "auxclkreq3_ck", &auxclkreq3_ck, CK_44XX), + CLK(NULL, "auxclkreq4_ck", &auxclkreq4_ck, CK_44XX), + CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_44XX), + CLK(NULL, "smp_twd", &smp_twd, CK_44XX), +}; + +#define L3_OPP50_RATE 100000000 +#define DPLL_CORE_M3_OPP50_RATE 200000000 +#define DPLL_CORE_M3_OPP100_RATE 320000000 +#define DPLL_CORE_M6_OPP50_RATE 200000000 +#define DPLL_CORE_M6_OPP100_RATE 266600000 +#define DPLL_CORE_M7_OPP50_RATE 133333333 +#define DPLL_CORE_M7_OPP100_RATE 266666666 +#define DPLL_PER_M3_OPP50_RATE 192000000 +#define DPLL_PER_M3_OPP100_RATE 256000000 +#define DPLL_PER_M6_OPP50_RATE 192000000 +#define DPLL_PER_M6_OPP100_RATE 384000000 + +static long omap4_virt_l3_round_rate(struct clk *clk, unsigned long rate) +{ + long parent_rate; + + if (!clk || !clk->parent) + return 0; + + if (clk->parent->round_rate) { + parent_rate = clk->parent->round_rate(clk, rate * 2); + if (parent_rate) + return parent_rate / 2; + } + return 0; +} + +static unsigned long omap4_virt_l3_recalc(struct clk *clk) +{ + if (!clk || !clk->parent) + return 0; + + return clk->parent->rate / 2; +} + +static int omap4_clksel_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + + if (!clk->set_rate || !clk->round_rate) + return ret; + + rate = clk->round_rate(clk, rate); + if (rate) { + ret = clk->set_rate(clk, rate); + if (!ret) + propagate_rate(clk); + } + return ret; +} + +struct virt_l3_ck_deps { + unsigned long core_m3_rate; + unsigned long core_m6_rate; + unsigned long core_m7_rate; + unsigned long per_m3_rate; + unsigned long per_m6_rate; +}; + +#define NO_OF_L3_OPPS 2 +#define L3_OPP_50_INDEX 0 +#define L3_OPP_100_INDEX 1 + +static struct virt_l3_ck_deps omap4_virt_l3_clk_deps[NO_OF_L3_OPPS] = { + { /* OPP 50 */ + .core_m3_rate = DPLL_CORE_M3_OPP50_RATE, + .core_m6_rate = DPLL_CORE_M6_OPP50_RATE, + .core_m7_rate = DPLL_CORE_M7_OPP50_RATE, + .per_m3_rate = DPLL_PER_M3_OPP50_RATE, + .per_m6_rate = DPLL_PER_M6_OPP50_RATE, + }, + { /* OPP 100 */ + .core_m3_rate = DPLL_CORE_M3_OPP100_RATE, + .core_m6_rate = DPLL_CORE_M3_OPP100_RATE, + .core_m7_rate = DPLL_CORE_M7_OPP100_RATE, + .per_m3_rate = DPLL_PER_M3_OPP100_RATE, + .per_m6_rate = DPLL_PER_M6_OPP100_RATE, + }, +}; + +static int omap4_virt_l3_set_rate(struct clk *clk, unsigned long rate) +{ + struct virt_l3_ck_deps *l3_deps; + + if (rate <= L3_OPP50_RATE) + l3_deps = &omap4_virt_l3_clk_deps[L3_OPP_50_INDEX]; + else + l3_deps = &omap4_virt_l3_clk_deps[L3_OPP_100_INDEX]; + + omap4_clksel_set_rate(&dpll_core_m3x2_ck, l3_deps->core_m3_rate); + omap4_clksel_set_rate(&dpll_core_m6x2_ck, l3_deps->core_m6_rate); + omap4_clksel_set_rate(&dpll_core_m7x2_ck, l3_deps->core_m7_rate); + omap4_clksel_set_rate(&dpll_per_m3x2_ck, l3_deps->per_m3_rate); + omap4_clksel_set_rate(&dpll_per_m6x2_ck, l3_deps->per_m6_rate); + omap4_clksel_set_rate(&dpll_core_m5x2_ck, rate * 2); + + clk->rate = rate; + return 0; +} int __init omap4xxx_clk_init(void) { struct omap_clk *c; - u32 cpu_clkflg; + u32 cpu_clkflg = 0; - if (cpu_is_omap44xx()) { - cpu_mask = RATE_IN_4430; + if (cpu_is_omap443x()) { + cpu_mask = RATE_IN_443X; cpu_clkflg = CK_443X; + } else if (cpu_is_omap446x()) { + cpu_mask = RATE_IN_446X; + cpu_clkflg = CK_446X; } clk_init(&omap2_clk_functions); diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 6cb6c03..b98a972 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm) arch_clkdm->clkdm_deny_idle(clkdm); } +/** + * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled + * @clkdm: struct clockdomain * + * + * Returns true if the clockdomain is in hardware-supervised + * idle mode, or 0 otherwise. + * + */ +int clkdm_is_idle(struct clockdomain *clkdm) +{ + if (!clkdm) + return -EINVAL; + + if (!arch_clkdm || !arch_clkdm->clkdm_is_idle) + return -EINVAL; + + pr_debug("clockdomain: reading idle state for %s\n", clkdm->name); + + return arch_clkdm->clkdm_is_idle(clkdm); +} + /* Clockdomain-to-clock framework interface code */ @@ -825,7 +846,12 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable) return -EINVAL; - if (atomic_inc_return(&clkdm->usecount) > 1) + /* + * For arch's with no autodeps, clkcm_clk_enable + * should be called for every clock instance that is + * enabled, so the clkdm can be force woken up. + */ + if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) return 0; /* Clockdomain now has one enabled downstream clock */ diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 5823584..085ed82 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -138,6 +138,7 @@ struct clockdomain { * @clkdm_wakeup: Force a clockdomain to wakeup * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain + * @clkdm_is_idle: Check if hw supervised idle transitions are enabled * @clkdm_clk_enable: Put the clkdm in right state for a clock enable * @clkdm_clk_disable: Put the clkdm in right state for a clock disable */ @@ -154,6 +155,7 @@ struct clkdm_ops { int (*clkdm_wakeup)(struct clockdomain *clkdm); void (*clkdm_allow_idle)(struct clockdomain *clkdm); void (*clkdm_deny_idle)(struct clockdomain *clkdm); + int (*clkdm_is_idle)(struct clockdomain *clkdm); int (*clkdm_clk_enable)(struct clockdomain *clkdm); int (*clkdm_clk_disable)(struct clockdomain *clkdm); }; @@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); void clkdm_allow_idle(struct clockdomain *clkdm); void clkdm_deny_idle(struct clockdomain *clkdm); +int clkdm_is_idle(struct clockdomain *clkdm); int clkdm_wakeup(struct clockdomain *clkdm); int clkdm_sleep(struct clockdomain *clkdm); diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index 48d0db7..db49baa 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -13,6 +13,7 @@ */ #include <linux/types.h> +#include <linux/errno.h> #include <plat/prcm.h> #include "prm.h" #include "prm2xxx_3xxx.h" @@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) _clkdm_del_autodeps(clkdm); } +static int omap2_clkdm_is_idle(struct clockdomain *clkdm) +{ + if (!clkdm->clktrctrl_mask) + return -1; + + return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); +} + static void _enable_hwsup(struct clockdomain *clkdm) { if (cpu_is_omap24xx()) @@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = { .clkdm_wakeup = omap2_clkdm_wakeup, .clkdm_allow_idle = omap2_clkdm_allow_idle, .clkdm_deny_idle = omap2_clkdm_deny_idle, + .clkdm_is_idle = omap2_clkdm_is_idle, .clkdm_clk_enable = omap2_clkdm_clk_enable, .clkdm_clk_disable = omap2_clkdm_clk_disable, }; @@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_wakeup = omap3_clkdm_wakeup, .clkdm_allow_idle = omap3_clkdm_allow_idle, .clkdm_deny_idle = omap3_clkdm_deny_idle, + .clkdm_is_idle = omap2_clkdm_is_idle, .clkdm_clk_enable = omap2_clkdm_clk_enable, .clkdm_clk_disable = omap2_clkdm_clk_disable, }; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index a1a4ecd..5024e63 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -93,15 +93,16 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) clkdm->cm_inst, clkdm->clkdm_offs); } -static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) +static int omap4_clkdm_is_idle(struct clockdomain *clkdm) { - bool hwsup = false; - - hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, clkdm->clkdm_offs); + return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs); +} - if (!hwsup) - clkdm_wakeup(clkdm); +static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) +{ + /* For every clock enable, force wakeup the clkdm */ + clkdm_wakeup(clkdm); return 0; } @@ -132,6 +133,7 @@ struct clkdm_ops omap4_clkdm_operations = { .clkdm_wakeup = omap4_clkdm_wakeup, .clkdm_allow_idle = omap4_clkdm_allow_idle, .clkdm_deny_idle = omap4_clkdm_deny_idle, + .clkdm_is_idle = omap4_clkdm_is_idle, .clkdm_clk_enable = omap4_clkdm_clk_enable, .clkdm_clk_disable = omap4_clkdm_clk_disable, }; diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index a607ec1..8d1a061 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -35,55 +35,55 @@ static struct clkdm_dep ducati_wkup_sleep_deps[] = { { .clkdm_name = "abe_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_2_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_dss_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_gfx_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_init_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_cfg_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_secure_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_wkup_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "tesla_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -91,15 +91,15 @@ static struct clkdm_dep ducati_wkup_sleep_deps[] = { static struct clkdm_dep iss_wkup_sleep_deps[] = { { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -107,11 +107,11 @@ static struct clkdm_dep iss_wkup_sleep_deps[] = { static struct clkdm_dep ivahd_wkup_sleep_deps[] = { { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -119,35 +119,35 @@ static struct clkdm_dep ivahd_wkup_sleep_deps[] = { static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = { { .clkdm_name = "abe_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_2_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_init_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_cfg_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -155,47 +155,47 @@ static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = { static struct clkdm_dep l3_dma_wkup_sleep_deps[] = { { .clkdm_name = "abe_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ducati_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_dss_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_init_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_cfg_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_secure_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_wkup_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -203,15 +203,15 @@ static struct clkdm_dep l3_dma_wkup_sleep_deps[] = { static struct clkdm_dep l3_dss_wkup_sleep_deps[] = { { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_2_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -219,15 +219,15 @@ static struct clkdm_dep l3_dss_wkup_sleep_deps[] = { static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = { { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -235,31 +235,31 @@ static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = { static struct clkdm_dep l3_init_wkup_sleep_deps[] = { { .clkdm_name = "abe_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_cfg_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_secure_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_wkup_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -267,15 +267,15 @@ static struct clkdm_dep l3_init_wkup_sleep_deps[] = { static struct clkdm_dep l4_secure_wkup_sleep_deps[] = { { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -283,59 +283,59 @@ static struct clkdm_dep l4_secure_wkup_sleep_deps[] = { static struct clkdm_dep mpuss_wkup_sleep_deps[] = { { .clkdm_name = "abe_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ducati_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_2_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_dss_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_gfx_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_init_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_cfg_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_secure_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_wkup_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "tesla_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -343,39 +343,39 @@ static struct clkdm_dep mpuss_wkup_sleep_deps[] = { static struct clkdm_dep tesla_wkup_sleep_deps[] = { { .clkdm_name = "abe_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "ivahd_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_1_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_2_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_emif_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l3_init_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_cfg_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_per_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { .clkdm_name = "l4_wkup_clkdm", - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX) }, { NULL }, }; @@ -387,7 +387,7 @@ static struct clockdomain l4_cefuse_44xx_clkdm = { .cm_inst = OMAP4430_CM2_CEFUSE_INST, .clkdm_offs = OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l4_cfg_44xx_clkdm = { @@ -398,7 +398,7 @@ static struct clockdomain l4_cfg_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CORE_L4CFG_CDOFFS, .dep_bit = OMAP4430_L4CFG_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain tesla_44xx_clkdm = { @@ -410,8 +410,8 @@ static struct clockdomain tesla_44xx_clkdm = { .dep_bit = OMAP4430_TESLA_STATDEP_SHIFT, .wkdep_srcs = tesla_wkup_sleep_deps, .sleepdep_srcs = tesla_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .flags = CLKDM_CAN_SWSUP, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_gfx_44xx_clkdm = { @@ -424,7 +424,7 @@ static struct clockdomain l3_gfx_44xx_clkdm = { .wkdep_srcs = l3_gfx_wkup_sleep_deps, .sleepdep_srcs = l3_gfx_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain ivahd_44xx_clkdm = { @@ -437,7 +437,7 @@ static struct clockdomain ivahd_44xx_clkdm = { .wkdep_srcs = ivahd_wkup_sleep_deps, .sleepdep_srcs = ivahd_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l4_secure_44xx_clkdm = { @@ -450,7 +450,7 @@ static struct clockdomain l4_secure_44xx_clkdm = { .wkdep_srcs = l4_secure_wkup_sleep_deps, .sleepdep_srcs = l4_secure_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l4_per_44xx_clkdm = { @@ -461,7 +461,7 @@ static struct clockdomain l4_per_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_L4PER_L4PER_CDOFFS, .dep_bit = OMAP4430_L4PER_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain abe_44xx_clkdm = { @@ -472,7 +472,7 @@ static struct clockdomain abe_44xx_clkdm = { .clkdm_offs = OMAP4430_CM1_ABE_ABE_CDOFFS, .dep_bit = OMAP4430_ABE_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_instr_44xx_clkdm = { @@ -481,7 +481,7 @@ static struct clockdomain l3_instr_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_L3INSTR_CDOFFS, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_init_44xx_clkdm = { @@ -493,8 +493,8 @@ static struct clockdomain l3_init_44xx_clkdm = { .dep_bit = OMAP4430_L3INIT_STATDEP_SHIFT, .wkdep_srcs = l3_init_wkup_sleep_deps, .sleepdep_srcs = l3_init_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .flags = CLKDM_CAN_SWSUP, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain mpuss_44xx_clkdm = { @@ -506,7 +506,7 @@ static struct clockdomain mpuss_44xx_clkdm = { .wkdep_srcs = mpuss_wkup_sleep_deps, .sleepdep_srcs = mpuss_wkup_sleep_deps, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain mpu0_44xx_clkdm = { @@ -516,7 +516,7 @@ static struct clockdomain mpu0_44xx_clkdm = { .cm_inst = OMAP4430_PRCM_MPU_CPU0_INST, .clkdm_offs = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain mpu1_44xx_clkdm = { @@ -526,7 +526,7 @@ static struct clockdomain mpu1_44xx_clkdm = { .cm_inst = OMAP4430_PRCM_MPU_CPU1_INST, .clkdm_offs = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_emif_44xx_clkdm = { @@ -537,7 +537,7 @@ static struct clockdomain l3_emif_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CORE_MEMIF_CDOFFS, .dep_bit = OMAP4430_MEMIF_STATDEP_SHIFT, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l4_ao_44xx_clkdm = { @@ -547,7 +547,7 @@ static struct clockdomain l4_ao_44xx_clkdm = { .cm_inst = OMAP4430_CM2_ALWAYS_ON_INST, .clkdm_offs = OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain ducati_44xx_clkdm = { @@ -559,8 +559,8 @@ static struct clockdomain ducati_44xx_clkdm = { .dep_bit = OMAP4430_DUCATI_STATDEP_SHIFT, .wkdep_srcs = ducati_wkup_sleep_deps, .sleepdep_srcs = ducati_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .flags = CLKDM_CAN_SWSUP, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_2_44xx_clkdm = { @@ -571,7 +571,7 @@ static struct clockdomain l3_2_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CORE_L3_2_CDOFFS, .dep_bit = OMAP4430_L3_2_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_1_44xx_clkdm = { @@ -582,7 +582,7 @@ static struct clockdomain l3_1_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CORE_L3_1_CDOFFS, .dep_bit = OMAP4430_L3_1_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_d2d_44xx_clkdm = { @@ -594,7 +594,7 @@ static struct clockdomain l3_d2d_44xx_clkdm = { .wkdep_srcs = l3_d2d_wkup_sleep_deps, .sleepdep_srcs = l3_d2d_wkup_sleep_deps, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain iss_44xx_clkdm = { @@ -605,8 +605,8 @@ static struct clockdomain iss_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CAM_CAM_CDOFFS, .wkdep_srcs = iss_wkup_sleep_deps, .sleepdep_srcs = iss_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .flags = CLKDM_CAN_SWSUP, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_dss_44xx_clkdm = { @@ -619,7 +619,7 @@ static struct clockdomain l3_dss_44xx_clkdm = { .wkdep_srcs = l3_dss_wkup_sleep_deps, .sleepdep_srcs = l3_dss_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l4_wkup_44xx_clkdm = { @@ -630,7 +630,7 @@ static struct clockdomain l4_wkup_44xx_clkdm = { .clkdm_offs = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS, .dep_bit = OMAP4430_L4WKUP_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain emu_sys_44xx_clkdm = { @@ -640,7 +640,7 @@ static struct clockdomain emu_sys_44xx_clkdm = { .cm_inst = OMAP4430_PRM_EMU_CM_INST, .clkdm_offs = OMAP4430_PRM_EMU_CM_EMU_CDOFFS, .flags = CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain l3_dma_44xx_clkdm = { @@ -652,7 +652,7 @@ static struct clockdomain l3_dma_44xx_clkdm = { .wkdep_srcs = l3_dma_wkup_sleep_deps, .sleepdep_srcs = l3_dma_wkup_sleep_deps, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct clockdomain *clockdomains_omap44xx[] __initdata = { diff --git a/arch/arm/mach-omap2/cm-regbits-44xx.h b/arch/arm/mach-omap2/cm-regbits-44xx.h index 9d47a05..4c4cbfa 100644 --- a/arch/arm/mach-omap2/cm-regbits-44xx.h +++ b/arch/arm/mach-omap2/cm-regbits-44xx.h @@ -106,6 +106,10 @@ #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT 9 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK (1 << 9) +/* Used by CM_L4CFG_CLKSTCTRL */ +#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_SHIFT 9 +#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_MASK (1 << 9) + /* Used by CM_CEFUSE_CLKSTCTRL */ #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT 9 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK (1 << 9) @@ -418,6 +422,10 @@ #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT 11 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK (1 << 11) +/* Used by CM_WKUP_CLKSTCTRL */ +#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_SHIFT 13 +#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_MASK (1 << 13) + /* * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, @@ -449,6 +457,10 @@ #define OMAP4430_CLKSEL_60M_SHIFT 24 #define OMAP4430_CLKSEL_60M_MASK (1 << 24) +/* Used by CM_MPU_MPU_CLKCTRL */ +#define OMAP4460_CLKSEL_ABE_DIV_MODE_SHIFT 25 +#define OMAP4460_CLKSEL_ABE_DIV_MODE_MASK (1 << 25) + /* Used by CM1_ABE_AESS_CLKCTRL */ #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT 24 #define OMAP4430_CLKSEL_AESS_FCLK_MASK (1 << 24) @@ -468,6 +480,10 @@ #define OMAP4430_CLKSEL_DIV_SHIFT 24 #define OMAP4430_CLKSEL_DIV_MASK (1 << 24) +/* Used by CM_MPU_MPU_CLKCTRL */ +#define OMAP4460_CLKSEL_EMIF_DIV_MODE_SHIFT 24 +#define OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK (1 << 24) + /* Used by CM_CAM_FDIF_CLKCTRL */ #define OMAP4430_CLKSEL_FCLK_SHIFT 24 #define OMAP4430_CLKSEL_FCLK_MASK (0x3 << 24) @@ -572,6 +588,14 @@ #define OMAP4430_D2D_STATDEP_SHIFT 18 #define OMAP4430_D2D_STATDEP_MASK (1 << 18) +/* Used by CM_CLKSEL_DPLL_MPU */ +#define OMAP4460_DCC_COUNT_MAX_SHIFT 24 +#define OMAP4460_DCC_COUNT_MAX_MASK (0xff << 24) + +/* Used by CM_CLKSEL_DPLL_MPU */ +#define OMAP4460_DCC_EN_SHIFT 22 +#define OMAP4460_DCC_EN_MASK (1 << 22) + /* * Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE, * CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, CM_SSC_DELTAMSTEP_DPLL_DDRPHY, @@ -1204,6 +1228,10 @@ #define OMAP4430_MODULEMODE_SHIFT 0 #define OMAP4430_MODULEMODE_MASK (0x3 << 0) +/* Used by CM_L4CFG_DYNAMICDEP */ +#define OMAP4460_MPU_DYNDEP_SHIFT 19 +#define OMAP4460_MPU_DYNDEP_MASK (1 << 19) + /* Used by CM_DSS_DSS_CLKCTRL */ #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT 9 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK (1 << 9) @@ -1298,6 +1326,10 @@ #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT 10 #define OMAP4430_OPTFCLKEN_SYS_CLK_MASK (1 << 10) +/* Used by CM_WKUP_BANDGAP_CLKCTRL */ +#define OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT 8 +#define OMAP4460_OPTFCLKEN_TS_FCLK_MASK (1 << 8) + /* Used by CM_DSS_DSS_CLKCTRL */ #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT 11 #define OMAP4430_OPTFCLKEN_TV_CLK_MASK (1 << 11) diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c index e94903b..94ccf46 100644 --- a/arch/arm/mach-omap2/common-board-devices.c +++ b/arch/arm/mach-omap2/common-board-devices.c @@ -85,17 +85,17 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, struct spi_board_info *spi_bi = &ads7846_spi_board_info; int err; - err = gpio_request(gpio_pendown, "TS PenDown"); - if (err) { - pr_err("Could not obtain gpio for TS PenDown: %d\n", err); - return; - } - - gpio_direction_input(gpio_pendown); - gpio_export(gpio_pendown, 0); + if (board_pdata && board_pdata->get_pendown_state) { + err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); + if (err) { + pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); + return; + } + gpio_export(gpio_pendown, 0); - if (gpio_debounce) - gpio_set_debounce(gpio_pendown, gpio_debounce); + if (gpio_debounce) + gpio_set_debounce(gpio_pendown, gpio_debounce); + } ads7846_config.gpio_pendown = gpio_pendown; diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h index eb80b3b..6797190 100644 --- a/arch/arm/mach-omap2/common-board-devices.h +++ b/arch/arm/mach-omap2/common-board-devices.h @@ -1,6 +1,8 @@ #ifndef __OMAP_COMMON_BOARD_DEVICES__ #define __OMAP_COMMON_BOARD_DEVICES__ +#define NAND_BLOCK_SIZE SZ_128K + struct twl4030_platform_data; struct mtd_partition; diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c index 3f20cbb..4ffcb54 100644 --- a/arch/arm/mach-omap2/common.c +++ b/arch/arm/mach-omap2/common.c @@ -127,6 +127,7 @@ static struct omap_globals omap4_globals = { .tap = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE), .ctrl = OMAP443X_SCM_BASE, .ctrl_pad = OMAP443X_CTRL_BASE, + .ctrl_wk_pad = OMAP443X_CTRL_WK_BASE, .prm = OMAP4430_PRM_BASE, .cm = OMAP4430_CM_BASE, .cm2 = OMAP4430_CM2_BASE, diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index da53ba3..5faf166 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -32,6 +32,7 @@ static void __iomem *omap2_ctrl_base; static void __iomem *omap4_ctrl_pad_base; +static void __iomem *omap4_ctrl_wk_pad_base; #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) struct omap3_scratchpad { @@ -146,6 +147,7 @@ static struct omap3_control_regs control_context; #define OMAP_CTRL_REGADDR(reg) (omap2_ctrl_base + (reg)) #define OMAP4_CTRL_PAD_REGADDR(reg) (omap4_ctrl_pad_base + (reg)) +#define OMAP4_CTRL_WK_PAD_REGADDR(reg) (omap4_ctrl_wk_pad_base + (reg)) void __init omap2_set_globals_control(struct omap_globals *omap2_globals) { @@ -160,6 +162,17 @@ void __init omap2_set_globals_control(struct omap_globals *omap2_globals) omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K); WARN_ON(!omap4_ctrl_pad_base); } + + /* + * static mapping, never released. omap4 Wakeup pad is seperate + * from the core, hence need to be mapped individually. + */ + if (omap2_globals->ctrl_wk_pad) { + omap4_ctrl_wk_pad_base = ioremap(omap2_globals->ctrl_wk_pad, + SZ_4K); + WARN_ON(!omap4_ctrl_wk_pad_base); + } + } void __iomem *omap_ctrl_base_get(void) @@ -204,16 +217,66 @@ void omap_ctrl_writel(u32 val, u16 offset) * registers. This APIs will work only for OMAP4 */ +u8 omap4_ctrl_pad_readb(u16 offset) +{ + return __raw_readb(OMAP4_CTRL_PAD_REGADDR(offset)); +} + +u16 omap4_ctrl_pad_readw(u16 offset) +{ + return __raw_readw(OMAP4_CTRL_PAD_REGADDR(offset)); +} + u32 omap4_ctrl_pad_readl(u16 offset) { return __raw_readl(OMAP4_CTRL_PAD_REGADDR(offset)); } +void omap4_ctrl_pad_writeb(u8 val, u16 offset) +{ + __raw_writeb(val, OMAP4_CTRL_PAD_REGADDR(offset)); +} + +void omap4_ctrl_pad_writew(u16 val, u16 offset) +{ + __raw_writew(val, OMAP4_CTRL_PAD_REGADDR(offset)); +} + void omap4_ctrl_pad_writel(u32 val, u16 offset) { __raw_writel(val, OMAP4_CTRL_PAD_REGADDR(offset)); } +u8 omap4_ctrl_wk_pad_readb(u16 offset) +{ + return __raw_readb(OMAP4_CTRL_WK_PAD_REGADDR(offset)); +} + +u16 omap4_ctrl_wk_pad_readw(u16 offset) +{ + return __raw_readw(OMAP4_CTRL_WK_PAD_REGADDR(offset)); +} + +u32 omap4_ctrl_wk_pad_readl(u16 offset) +{ + return __raw_readl(OMAP4_CTRL_WK_PAD_REGADDR(offset)); +} + +void omap4_ctrl_wk_pad_writeb(u8 val, u16 offset) +{ + __raw_writeb(val, OMAP4_CTRL_WK_PAD_REGADDR(offset)); +} + +void omap4_ctrl_wk_pad_writew(u16 val, u16 offset) +{ + __raw_writew(val, OMAP4_CTRL_WK_PAD_REGADDR(offset)); +} + +void omap4_ctrl_wk_pad_writel(u32 val, u16 offset) +{ + __raw_writel(val, OMAP4_CTRL_WK_PAD_REGADDR(offset)); +} + #ifdef CONFIG_ARCH_OMAP3 /** diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h index a016c8b..1aa7632 100644 --- a/arch/arm/mach-omap2/control.h +++ b/arch/arm/mach-omap2/control.h @@ -195,6 +195,7 @@ #define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO 0x249 #define OMAP44XX_CONTROL_FUSE_CORE_OPP50 0x254 #define OMAP44XX_CONTROL_FUSE_CORE_OPP100 0x257 +#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV 0x25A /* AM35XX only CONTROL_GENERAL register offsets */ #define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038) @@ -338,6 +339,14 @@ #define AM35XX_HECC_SW_RST BIT(3) #define AM35XX_VPFE_PCLK_SW_RST BIT(4) +/* CONTROL_PADCONF_X bits */ +#define OMAP44XX_PADCONF_WAKEUPEVENT0 (1 << 15) +#define OMAP44XX_PADCONF_WAKEUPEVENT1 (1 << 30) +#define OMAP44XX_PADCONF_WAKEUPENABLE0 (1 << 14) +#define OMAP44XX_PADCONF_WAKEUPENABLE1 (1 << 31) +#define OMAP44XX_PADCONF_OFFMODEENABLE0 (1 << 9) +#define OMAP44XX_PADCONF_OFFMODEENABLE1 (1 << 25) + /* * CONTROL OMAP STATUS register to identify OMAP3 features */ @@ -378,11 +387,21 @@ extern void __iomem *omap_ctrl_base_get(void); extern u8 omap_ctrl_readb(u16 offset); extern u16 omap_ctrl_readw(u16 offset); extern u32 omap_ctrl_readl(u16 offset); +extern u8 omap4_ctrl_pad_readb(u16 offset); +extern u16 omap4_ctrl_pad_readw(u16 offset); extern u32 omap4_ctrl_pad_readl(u16 offset); +extern u8 omap4_ctrl_wk_pad_readb(u16 offset); +extern u16 omap4_ctrl_wk_pad_readw(u16 offset); +extern u32 omap4_ctrl_wk_pad_readl(u16 offset); extern void omap_ctrl_writeb(u8 val, u16 offset); extern void omap_ctrl_writew(u16 val, u16 offset); extern void omap_ctrl_writel(u32 val, u16 offset); +extern void omap4_ctrl_pad_writeb(u8 val, u16 offset); +extern void omap4_ctrl_pad_writew(u16 val, u16 offset); extern void omap4_ctrl_pad_writel(u32 val, u16 offset); +extern void omap4_ctrl_wk_pad_writeb(u8 val, u16 offset); +extern void omap4_ctrl_wk_pad_writew(u16 val, u16 offset); +extern void omap4_ctrl_wk_pad_writel(u32 val, u16 offset); extern void omap3_save_scratchpad_contents(void); extern void omap3_clear_scratchpad_contents(void); @@ -400,11 +419,21 @@ extern int omap3_ctrl_save_padconf(void); #define omap_ctrl_readb(x) 0 #define omap_ctrl_readw(x) 0 #define omap_ctrl_readl(x) 0 -#define omap4_ctrl_pad_readl(x) 0 +#define omap4_ctrl_pad_readb(x) 0 +#define omap4_ctrl_pad_readw(x) 0 +#define omap4_ctrl_pad_readl(x) 0 +#define omap4_ctrl_wk_pad_readb(x) 0 +#define omap4_ctrl_wk_pad_readw(x) 0 +#define omap4_ctrl_wk_pad_readl(x) 0 #define omap_ctrl_writeb(x, y) WARN_ON(1) #define omap_ctrl_writew(x, y) WARN_ON(1) #define omap_ctrl_writel(x, y) WARN_ON(1) +#define omap4_ctrl_pad_writeb(x, y) WARN_ON(1) +#define omap4_ctrl_pad_writew(x, y) WARN_ON(1) #define omap4_ctrl_pad_writel(x, y) WARN_ON(1) +#define omap4_ctrl_wk_pad_writeb(x, y) WARN_ON(1) +#define omap4_ctrl_wk_pad_writew(x, y) WARN_ON(1) +#define omap4_ctrl_wk_pad_writel(x, y) WARN_ON(1) #endif #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c new file mode 100644 index 0000000..9f085da --- /dev/null +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -0,0 +1,381 @@ +/* + * OMAP4 CPU idle Routines + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Rajendra Nayak <rnayak@ti.com> + * Santosh Shilimkar <santosh.shilimkar@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/sched.h> +#include <linux/cpuidle.h> +#include <linux/clockchips.h> +#include <linux/notifier.h> +#include <linux/cpu.h> + +#include <asm/proc-fns.h> + +#include <mach/omap4-common.h> + +#include <plat/gpio.h> + +#include "pm.h" +#include "prm.h" + +#ifdef CONFIG_CPU_IDLE + +#define OMAP4_MAX_STATES 4 + +#define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap4_enter_idle_bm() */ + +/* C1 - CPU0 WFI + CPU1 OFF + MPU ON + CORE ON */ +#define OMAP4_STATE_C1 0 +/* C2 - CPU0 INA + CPU1 OFF + MPU INA + CORE INA */ +#define OMAP4_STATE_C2 1 +/* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE CSWR */ +#define OMAP4_STATE_C3 2 +/* C4 - CPU0 OFF + CPU1 OFF + MPU RET + CORE CSWR */ +#define OMAP4_STATE_C4 3 + +struct omap4_processor_cx { + u8 valid; + u8 type; + u32 exit_latency; + u32 target_residency; + u32 cpu0_state; + u32 mpu_state; + u32 mpu_logic_state; + u32 core_state; + u32 core_logic_state; + u32 flags; + const char *desc; +}; + +struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES]; +static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd; +static int needs_state_data_update; +static unsigned int state_flags = CPUIDLE_FLAG_IGNORE; + +/* + * FIXME: Full latency numbers needs to be updated as part of + * cpuidle CORE retention support. + * Currently only MPUSS latency numbers are added based on + * measurements done internally. The numbers for MPUSS are + * not board dependent and hence set directly here instead of + * passing it from board files. + */ +static struct cpuidle_params cpuidle_params_table[] = { + /* C1 - CPU0 WFI + CPU1 OFF + MPU ON + CORE ON */ + {.exit_latency = 2 + 2, .target_residency = 5, .valid = 1}, + /* C2 - CPU0 INA + CPU1 OFF + MPU INA + CORE INA */ + {.exit_latency = 140 + 160, .target_residency = 300, .valid = 1}, + /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE CSWR */ + {.exit_latency = 1516 + 3220, .target_residency = 15000, .valid = 1}, + /* C4 - CPU0 OFF + CPU1 OFF + MPU OSWR + CORE OSWR */ + {.exit_latency = 1644 + 3298, .target_residency = 39000, .valid = 0}, +}; + +static bool omap4_idle_bm_busy(void) +{ + if (!omap4_can_sleep()) + return true; + return false; +} + +/** + * omap4_prepare_idle - Update C-state parameters dynamically + * @dev: cpuidle device + * + * Called from the CPUidle framework to prepare the device + * for idle before before calling the governor's select function. + */ +static int omap4_prepare_idle(struct cpuidle_device *dev) +{ + int i, ret = 0; + + if (!needs_state_data_update) + return ret; + + /* + * Update the C-state flags based on CPU1 online + * or offline state. On OMAP4, the low power C-states + * are made available when only CPU1 is offline. + */ + for (i = OMAP4_STATE_C2; i < OMAP4_MAX_STATES; i++) + dev->states[i].flags = state_flags; + + return ret; +} + +/** + * omap4_enter_idle - Programs OMAP4 to enter the specified state + * @dev: cpuidle device + * @state: The target state to be programmed + * + * Called from the CPUidle framework to program the device to the + * specified low power state selected by the governor. + * Returns the amount of time spent in the low power state. + */ +static int omap4_enter_idle(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + struct omap4_processor_cx *cx = cpuidle_get_statedata(state); + struct timespec ts_preidle, ts_postidle, ts_idle; + u32 cpu1_state; + int cpu_id = smp_processor_id(); + + /* Used to keep track of the total time in idle */ + getnstimeofday(&ts_preidle); + + local_irq_disable(); + local_fiq_disable(); + + /* + * Continue to do only WFI on CPU0 till CPU1 hits OFF state. + * This is necessary to honour hardware recommondation + * of triggeing all the possible low power modes once CPU1 is + * out of coherency and in OFF mode. + * Update dev->last_state so that governor stats reflects right + * data. + */ + cpu1_state = pwrdm_read_pwrst(cpu1_pd); + if ((cpu1_state != PWRDM_POWER_OFF) || (!cx->valid)) { + dev->last_state = dev->safe_state; + cx = cpuidle_get_statedata(dev->safe_state); + } + + pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); + omap_set_pwrdm_state(mpu_pd, cx->mpu_state); + pwrdm_set_logic_retst(core_pd, cx->core_logic_state); + omap_set_pwrdm_state(core_pd, cx->core_state); + + if (cx->type > OMAP4_STATE_C1) + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); + + omap4_enter_sleep(dev->cpu, cx->cpu0_state); + + /* restore the MPU and CORE states to ON */ + omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON); + omap_set_pwrdm_state(core_pd, PWRDM_POWER_ON); + if (cx->type > OMAP4_STATE_C1) + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); + + getnstimeofday(&ts_postidle); + ts_idle = timespec_sub(ts_postidle, ts_preidle); + + local_irq_enable(); + local_fiq_enable(); + + return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; +} + +/** + * omap4_enter_idle_bm - Checks for any bus activity + * @dev: cpuidle device + * @state: The target state to be programmed + * + * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This + * function checks for any pending activity and then programs the + * device to the specified or a safer state. + */ +static int omap4_enter_idle_bm(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + if ((omap4_idle_bm_busy())) { + BUG_ON(!dev->safe_state); + state = dev->safe_state; + } + + dev->last_state = state; + return omap4_enter_idle(dev, state); +} + +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); + +/** + * omap4_init_power_states - Initialises the OMAP4 specific C states. + * + * Below is the desciption of each C state. + * C1 : CPUx wfi + MPU inative + Core inactive + */ +void omap4_init_power_states(void) +{ + /* + * C1 - CPU0 WFI + CPU1 OFF + MPU ON + CORE ON + */ + omap4_power_states[OMAP4_STATE_C1].valid = + cpuidle_params_table[OMAP4_STATE_C1].valid; + omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1; + omap4_power_states[OMAP4_STATE_C1].exit_latency= + cpuidle_params_table[OMAP4_STATE_C1].exit_latency; + omap4_power_states[OMAP4_STATE_C1].target_residency = + cpuidle_params_table[OMAP4_STATE_C1].target_residency; + omap4_power_states[OMAP4_STATE_C1].cpu0_state = PWRDM_POWER_ON; + omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON; + omap4_power_states[OMAP4_STATE_C1].mpu_logic_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON; + omap4_power_states[OMAP4_STATE_C1].core_logic_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; + omap4_power_states[OMAP4_STATE_C1].desc = "MPU ON + CORE ON"; + + /* + * C2 - CPU0 INA + CPU1 OFF + MPU INA + CORE INA + */ + omap4_power_states[OMAP4_STATE_C2].valid = + cpuidle_params_table[OMAP4_STATE_C2].valid; + omap4_power_states[OMAP4_STATE_C2].type = OMAP4_STATE_C2; + omap4_power_states[OMAP4_STATE_C2].exit_latency = + cpuidle_params_table[OMAP4_STATE_C2].exit_latency; + omap4_power_states[OMAP4_STATE_C2].target_residency = + cpuidle_params_table[OMAP4_STATE_C2].target_residency; + omap4_power_states[OMAP4_STATE_C2].cpu0_state = PWRDM_POWER_INACTIVE; + omap4_power_states[OMAP4_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE; + omap4_power_states[OMAP4_STATE_C2].mpu_logic_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C2].core_state = PWRDM_POWER_INACTIVE; + omap4_power_states[OMAP4_STATE_C2].core_logic_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; + omap4_power_states[OMAP4_STATE_C2].desc = "MPU INA + CORE INA"; + + /* + * C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE CSWR + */ + omap4_power_states[OMAP4_STATE_C3].valid = + cpuidle_params_table[OMAP4_STATE_C3].valid; + omap4_power_states[OMAP4_STATE_C3].type = OMAP4_STATE_C3; + omap4_power_states[OMAP4_STATE_C3].exit_latency = + cpuidle_params_table[OMAP4_STATE_C3].exit_latency; + omap4_power_states[OMAP4_STATE_C3].target_residency = + cpuidle_params_table[OMAP4_STATE_C3].target_residency; + omap4_power_states[OMAP4_STATE_C3].cpu0_state = PWRDM_POWER_OFF; + omap4_power_states[OMAP4_STATE_C3].mpu_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C3].mpu_logic_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C3].core_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C3].core_logic_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap4_power_states[OMAP4_STATE_C3].desc = "MPU CSWR + CORE CSWR"; + + /* + * C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE CSWR + */ + omap4_power_states[OMAP4_STATE_C4].valid = + cpuidle_params_table[OMAP4_STATE_C4].valid; + omap4_power_states[OMAP4_STATE_C4].type = OMAP4_STATE_C4; + omap4_power_states[OMAP4_STATE_C4].exit_latency = + cpuidle_params_table[OMAP4_STATE_C4].exit_latency; + omap4_power_states[OMAP4_STATE_C4].target_residency = + cpuidle_params_table[OMAP4_STATE_C4].target_residency; + omap4_power_states[OMAP4_STATE_C4].cpu0_state = PWRDM_POWER_OFF; + omap4_power_states[OMAP4_STATE_C4].mpu_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C4].mpu_logic_state = PWRDM_POWER_OFF; + omap4_power_states[OMAP4_STATE_C4].core_state = PWRDM_POWER_RET; + omap4_power_states[OMAP4_STATE_C4].core_logic_state = PWRDM_POWER_OFF; + omap4_power_states[OMAP4_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_CHECK_BM; + omap4_power_states[OMAP4_STATE_C4].desc = "MPU OSWR + CORE OSWR"; + +} + +struct cpuidle_driver omap4_idle_driver = { + .name = "omap4_idle", + .owner = THIS_MODULE, +}; + +/* + * CPU hotplug notifier to update the C-states when + * CPU1 is offline or onine. While updating C-state flag, + * keep the cpuidle disabled. + */ +static int __cpuinit omap_cpu_hotplug_notify(struct notifier_block *self, + unsigned long action, void *unused) +{ + switch (action) { + case CPU_ONLINE: + disable_hlt(); + needs_state_data_update = 1; + state_flags = CPUIDLE_FLAG_IGNORE; + enable_hlt(); + break; + case CPU_DEAD: + disable_hlt(); + needs_state_data_update = 1; + state_flags = CPUIDLE_FLAG_TIME_VALID; + enable_hlt(); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block __refdata omap_ilde_hotplug_notifier = { + .notifier_call = omap_cpu_hotplug_notify, +}; + +/** + * omap4_idle_init - Init routine for OMAP4 idle + * + * Registers the OMAP4 specific cpuidle driver with the cpuidle + * framework with the valid set of states. + */ +int __init omap4_idle_init(void) +{ + int cpu_id = 0, i, count = 0, ret; + struct omap4_processor_cx *cx; + struct cpuidle_state *state; + struct cpuidle_device *dev; + + mpu_pd = pwrdm_lookup("mpu_pwrdm"); + cpu1_pd = pwrdm_lookup("cpu1_pwrdm"); + core_pd = pwrdm_lookup("core_pwrdm"); + + omap4_init_power_states(); + cpuidle_register_driver(&omap4_idle_driver); + + dev = &per_cpu(omap4_idle_dev, cpu_id); + dev->cpu = cpu_id; + count = 0; + for (i = OMAP4_STATE_C1; i < OMAP4_MAX_STATES; i++) { + cx = &omap4_power_states[i]; + state = &dev->states[count]; + + if (!cx->valid) + continue; + cpuidle_set_statedata(state, cx); + state->exit_latency = cx->exit_latency; + state->target_residency = cx->target_residency; + state->flags = cx->flags; + if (cx->type == OMAP4_STATE_C1) + dev->safe_state = state; + state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ? + omap4_enter_idle_bm : omap4_enter_idle; + + sprintf(state->name, "C%d", count+1); + strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); + count++; + } + + if (!count) + return -EINVAL; + dev->state_count = count; + dev->prepare = omap4_prepare_idle; + + if (cpuidle_register_device(dev)) { + pr_err("%s: CPUidle register device failed\n", __func__); + return -EIO; + } + + ret = register_hotcpu_notifier(&omap_ilde_hotplug_notifier); + if (ret) + return ret; + + return 0; +} +#else +int __init omap4_idle_init(void) +{ + return 0; +} +#endif /* CONFIG_CPU_IDLE */ diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 7b85585..d2b7058 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -29,6 +29,7 @@ #include <mach/gpio.h> #include <plat/mmc.h> #include <plat/dma.h> +#include <plat/gpu.h> #include <plat/omap_hwmod.h> #include <plat/omap_device.h> #include <plat/omap4-keypad.h> @@ -97,7 +98,7 @@ static int __init omap4_l3_init(void) WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name); - return PTR_ERR(od); + return IS_ERR(od) ? PTR_ERR(od) : 0; } postcore_initcall(omap4_l3_init); @@ -292,6 +293,21 @@ static inline void omap_init_mbox(void) { } static inline void omap_init_sti(void) {} +#if defined CONFIG_ARCH_OMAP4 + +static struct platform_device omap_abe_dai = { + .name = "omap-abe-dai", + .id = -1, +}; + +static inline void omap_init_abe(void) +{ + platform_device_register(&omap_abe_dai); +} +#else +static inline void omap_init_abe(void) {} +#endif + #if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) static struct platform_device omap_pcm = { @@ -673,6 +689,63 @@ static void omap_init_vout(void) static inline void omap_init_vout(void) {} #endif +static struct omap_device_pm_latency omap_gpu_latency[] = { + [0] = { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static struct platform_device omap_omaplfb_device = { + .name = "omaplfb", + .id = -1, +}; + + +static void omap_init_gpu(void) +{ + struct omap_hwmod *oh; + struct omap_device *od; + int max_omap_gpu_hwmod_name_len = 16; + char oh_name[max_omap_gpu_hwmod_name_len]; + int l; + struct gpu_platform_data *pdata; + char *name = "pvrsrvkm"; + + l = snprintf(oh_name, max_omap_gpu_hwmod_name_len, + "gpu"); + WARN(l >= max_omap_gpu_hwmod_name_len, + "String buffer overflow in GPU device setup\n"); + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + + pr_err("omap_init_gpu: Could not look up %s\n", oh_name); + return; + } + + pdata = kzalloc(sizeof(struct gpu_platform_data), + GFP_KERNEL); + if (!pdata) { + pr_err("omap_init_gpu: Platform data memory allocation failed\n"); + return; + } + + pdata->device_enable = omap_device_enable; + pdata->device_idle = omap_device_idle; + pdata->device_shutdown = omap_device_shutdown; + + od = omap_device_build(name, 0, oh, pdata, + sizeof(struct gpu_platform_data), + omap_gpu_latency, ARRAY_SIZE(omap_gpu_latency), 0); + WARN(IS_ERR(od), "Could not build omap_device for %s %s\n", + name, oh_name); + + kfree(pdata); + platform_device_register(&omap_omaplfb_device); +} + /*-------------------------------------------------------------------------*/ static int __init omap2_init_devices(void) @@ -681,6 +754,7 @@ static int __init omap2_init_devices(void) * please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ + omap_init_abe(); omap_init_audio(); omap_init_camera(); omap_init_mbox(); @@ -691,6 +765,7 @@ static int __init omap2_init_devices(void) omap_init_sham(); omap_init_aes(); omap_init_vout(); + omap_init_gpu(); return 0; } diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 4e4da61..aa6e517 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -19,8 +19,13 @@ #include <plat/clock.h> #include "clock.h" +#include "cm1_44xx.h" #include "cm-regbits-44xx.h" +#define OMAP_1GHz 1000000000 +#define OMAP_920MHz 920000000 +#define OMAP_748MHz 748000000 + /* Supported only on OMAP4 */ int omap4_dpllmx_gatectrl_read(struct clk *clk) { @@ -82,3 +87,110 @@ const struct clkops clkops_omap4_dpllmx_ops = { .deny_idle = omap4_dpllmx_deny_gatectrl, }; +int omap4460_mpu_dpll_set_rate(struct clk *clk, unsigned long rate) +{ + struct dpll_data *dd; + u32 v; + unsigned long dpll_rate; + + if (!clk || !rate || !clk->parent) + return -EINVAL; + + dd = clk->parent->dpll_data; + + if (!dd) + return -EINVAL; + + if (!clk->parent->set_rate) + return -EINVAL; + + /* + * On OMAP4460, to obtain MPU DPLL frequency higher + * than 1GHz, DCC (Duty Cycle Correction) needs to + * be enabled. + * And needs to be kept disabled for < 1 Ghz. + */ + dpll_rate = omap2_get_dpll_rate(clk->parent); + v = __raw_readl(dd->mult_div1_reg); + if (rate < OMAP_1GHz) { + if (rate == dpll_rate) + return 0; + /* If DCC is enabled, disable it */ + if (v & OMAP4460_DCC_EN_MASK) { + v &= ~OMAP4460_DCC_EN_MASK; + __raw_writel(v, dd->mult_div1_reg); + } + clk->parent->set_rate(clk->parent, rate); + } else { + if (rate == dpll_rate/2) + return 0; + v &= ~OMAP4460_DCC_COUNT_MAX_MASK; + v |= (5 << OMAP4460_DCC_COUNT_MAX_SHIFT); + v |= OMAP4460_DCC_EN_MASK; + __raw_writel(v, dd->mult_div1_reg); + /* + * On 4460, the MPU clk for frequencies higher than 1Ghz + * is sourced from CLKOUTX2_M3, instead of CLKOUT_M2, while + * value of M3 is fixed to 1. Hence for frequencies higher + * than 1 Ghz, lock the DPLL at half the rate so the + * CLKOUTX2_M3 then matches the requested rate. + */ + clk->parent->set_rate(clk->parent, rate/2); + } + + clk->rate = rate; + + /* + * The interconnect frequency to EMIF should + * be switched between MPU clk divide by 4 (for + * frequencies higher than 920Mhz) and MPU clk divide + * by 2 (for frequencies lower than or equal to 920Mhz) + * Also the async bridge to ABE must be MPU clk divide + * by 8 for MPU clk > 748Mhz and MPU clk divide by 4 + * for lower frequencies. + */ + v = __raw_readl(OMAP4430_CM_MPU_MPU_CLKCTRL); + if (rate > OMAP_920MHz) + v |= OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK; + else + v &= ~OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK; + + if (rate > OMAP_748MHz) + v |= OMAP4460_CLKSEL_ABE_DIV_MODE_MASK; + else + v &= ~OMAP4460_CLKSEL_ABE_DIV_MODE_MASK; + __raw_writel(v, OMAP4430_CM_MPU_MPU_CLKCTRL); + + return 0; +} + +long omap4460_mpu_dpll_round_rate(struct clk *clk, unsigned long rate) +{ + if (!clk || !rate || !clk->parent) + return -EINVAL; + + if (clk->parent->round_rate) + return clk->parent->round_rate(clk, rate); + else + return 0; +} + +unsigned long omap4460_mpu_dpll_recalc(struct clk *clk) +{ + struct dpll_data *dd; + u32 v; + + if (!clk || !clk->parent) + return -EINVAL; + + dd = clk->parent->dpll_data; + + if (!dd) + return -EINVAL; + + v = __raw_readl(dd->mult_div1_reg); + if (v & OMAP4460_DCC_EN_MASK) + return omap2_get_dpll_rate(clk->parent) * 2; + else + return omap2_get_dpll_rate(clk->parent); +} diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c new file mode 100644 index 0000000..8c82f2c --- /dev/null +++ b/arch/arm/mach-omap2/dvfs.c @@ -0,0 +1,988 @@ +/* + * OMAP3/OMAP4 DVFS Management Routines + * + * Author: Vishwanath BS <vishwanath.bs@ti.com> + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Vishwanath BS <vishwanath.bs@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/err.h> +#include <linux/spinlock.h> +#include <linux/plist.h> +#include <linux/slab.h> +#include <linux/opp.h> +#include <linux/clk.h> +#include <plat/common.h> +#include <plat/omap_device.h> +#include <plat/omap_hwmod.h> +#include <plat/clock.h> +#include "dvfs.h" +#include "smartreflex.h" +#include "powerdomain.h" + +/** + * DOC: Introduction + * ================= + * DVFS is a technique that uses the optimal operating frequency and voltage to + * allow a task to be performed in the required amount of time. + * OMAP processors have voltage domains whose voltage can be scaled to + * various levels depending on which the operating frequencies of certain + * devices belonging to the domain will also need to be scaled. This voltage + * frequency tuple is known as Operating Performance Point (OPP). A device + * can have multiple OPP's. Also a voltage domain could be shared between + * multiple devices. Also there could be dependencies between various + * voltage domains for maintaining system performance like VDD<X> + * should be at voltage v1 when VDD<Y> is at voltage v2. + * + * The design of this framework takes into account all the above mentioned + * points. To summarize the basic design of DVFS framework:- + * + * 1. Have device opp tables for each device whose operating frequency can be + * scaled. This is easy now due to the existance of hwmod layer which + * allow storing of device specific info. The device opp tables contain + * the opp pairs (frequency voltage tuples), the voltage domain pointer + * to which the device belongs to, the device specific set_rate and + * get_rate API's which will do the actual scaling of the device frequency + * and retrieve the current device frequency. + * 2. Introduce use counting on a per VDD basis. This is to take care multiple + * requests to scale a VDD. The VDD will be scaled to the maximum of the + * voltages requested. + * 3. Keep track of all scalable devices belonging to a particular voltage + * domain the voltage layer. + * 4. Keep track of frequency requests for each of the device. This will enable + * to scale individual devices to different frequency (even w/o scaling + * voltage aka frequency throttling) + * 5. Generic dvfs API that can be called by anybody to scale a device opp. + * This API takes the device pointer and frequency to which the device + * needs to be scaled to. This API then internally finds out the voltage + * domain to which the device belongs to and the voltage to which the voltage + * domain needs to be put to for the device to be scaled to the new frequency + * from he device opp table. Then this API will add requested frequency into + * the corresponding target device frequency list and add voltage request to + * the corresponding vdd. Subsequently it calls voltage scale function which + * will find out the highest requested voltage for the given vdd and scales + * the voltage to the required one. It also runs through the list of all + * scalable devices belonging to this voltage domain and scale them to the + * appropriate frequencies using the set_rate pointer in the device opp + * tables. + * 6. Handle inter VDD dependecies. + * + * + * DOC: The Core DVFS data structure: + * ================================== + * Structure Name Example Tree + * --------- + * /|\ +-------------------+ +-------------------+ + * | |User2 (dev2, freq2)+---\ |User4 (dev4, freq4)+---\ + * | +-------------------+ | +-------------------+ | + * (struct omap_dev_user_list) | | + * | +-------------------+ | +-------------------+ | + * | |User1 (dev1, freq1)+---| |User3 (dev3, freq3)+---| + * \|/ +-------------------+ | +-------------------+ | + * --------- | | + * /|\ +------------+------+ +---------------+--+ + * | | DEV1 (dev, | | DEV2 (dev) | + * (struct omap_vdd_dev_list)|omap_dev_user_list)| |omap_dev_user_list| + * | +------------+------+ +--+---------------+ + * \|/ /|\ /-----+-------------+------> others.. + * --------- Frequency | + * /|\ +--+------------------+ + * | | VDD_n | + * | | (omap_vdd_dev_list, | + * (struct omap_vdd_dvfs_info)** | omap_vdd_user_list) | + * | +--+------------------+ + * | | (ROOT NODE: omap_dvfs_info_list) + * \|/ | + * --------- Voltage \---+-------------+----------> others.. + * /|\ \|/ +-------+----+ +-----+--------+ + * | | vdd_user2 | | vdd_user3 | + * (struct omap_vdd_user_list) | (dev, volt)| | (dev, volt) | + * \|/ +------------+ +--------------+ + * --------- + * Key: ** -> Root of the tree. + * NOTE: we use the priority to store the voltage/frequency + * + * For voltage dependency description, see: struct dependency: + * voltagedomain -> (description of the voltagedomain) + * omap_vdd_info -> (vdd information) + * omap_vdd_dep_info[]-> (stores array of depedency info) + * omap_vdd_dep_volt[] -> (stores array of maps) + * (main_volt -> dep_volt) (a singular map) + */ + +/* Macros to give idea about scaling directions */ +#define DVFS_VOLT_SCALE_DOWN 0 +#define DVFS_VOLT_SCALE_NONE 1 +#define DVFS_VOLT_SCALE_UP 2 + +/** + * struct omap_dev_user_list - Structure maitain userlist per devide + * @dev: The device requesting for a particular frequency + * @node: The list head entry + * + * Using this structure, user list (requesting dev * and frequency) for + * each device is maintained. This is how we can have different devices + * at different frequencies (to support frequency locking and throttling). + * Even if one of the devices in a given vdd has locked it's frequency, + * other's can still scale their frequency using this list. + * If no one has placed a frequency request for a device, then device is + * set to the frequency from it's opp table. + */ +struct omap_dev_user_list { + struct device *dev; + struct plist_node node; +}; + +/** + * struct omap_vdd_dev_list - Device list per vdd + * @dev: The device belonging to a particular vdd + * @node: The list head entry + * @freq_user_list: The list of users for vdd device + * @clk: frequency control clock for this dev + * @user_lock: The lock for plist manipulation + */ +struct omap_vdd_dev_list { + struct device *dev; + struct list_head node; + struct plist_head freq_user_list; + struct clk *clk; + spinlock_t user_lock; /* spinlock for plist */ +}; + +/** + * struct omap_vdd_user_list - The per vdd user list + * @dev: The device asking for the vdd to be set at a particular + * voltage + * @node: The list head entry + */ +struct omap_vdd_user_list { + struct device *dev; + struct plist_node node; +}; + +/** + * struct omap_vdd_dvfs_info - The per vdd dvfs info + * @node: list node for vdd_dvfs_info list + * @user_lock: spinlock for plist operations + * @vdd_user_list: The vdd user list + * @voltdm: Voltage domains for which dvfs info stored + * @dev_list: Device list maintained per domain + * + * This is a fundamental structure used to store all the required + * DVFS related information for a vdd. + */ +struct omap_vdd_dvfs_info { + struct list_head node; + + spinlock_t user_lock; /* spin lock */ + struct plist_head vdd_user_list; + struct voltagedomain *voltdm; + struct list_head dev_list; +}; + +static LIST_HEAD(omap_dvfs_info_list); +static DEFINE_MUTEX(omap_dvfs_lock); + +/* Dvfs scale helper function */ +static int _dvfs_scale(struct device *req_dev, struct device *target_dev, + struct omap_vdd_dvfs_info *tdvfs_info); + +/* Few search functions to traverse and find pointers of interest */ + +/** + * _dvfs_info_to_dev() - Locate the parent device associated to dvfs_info + * @dvfs_info: dvfs_info to search for + * + * Returns NULL on failure. + */ +static struct device *_dvfs_info_to_dev(struct omap_vdd_dvfs_info *dvfs_info) +{ + struct omap_vdd_dev_list *tmp_dev; + if (IS_ERR_OR_NULL(dvfs_info)) + return NULL; + if (list_empty(&dvfs_info->dev_list)) + return NULL; + tmp_dev = list_first_entry(&dvfs_info->dev_list, + struct omap_vdd_dev_list, node); + return tmp_dev->dev; +} + +/** + * _dev_to_dvfs_info() - Locate the dvfs_info for a device + * @dev: dev to search for + * + * Returns NULL on failure. + */ +static struct omap_vdd_dvfs_info *_dev_to_dvfs_info(struct device *dev) +{ + struct omap_vdd_dvfs_info *dvfs_info; + struct omap_vdd_dev_list *temp_dev; + + if (IS_ERR_OR_NULL(dev)) + return NULL; + + list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) { + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == dev) + return dvfs_info; + } + } + + return NULL; +} + +/** + * _voltdm_to_dvfs_info() - Locate a dvfs_info given a voltdm pointer + * @voltdm: voltdm to search for + * + * Returns NULL on failure. + */ +static +struct omap_vdd_dvfs_info *_voltdm_to_dvfs_info(struct voltagedomain *voltdm) +{ + struct omap_vdd_dvfs_info *dvfs_info; + + if (IS_ERR_OR_NULL(voltdm)) + return NULL; + + list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) { + if (dvfs_info->voltdm == voltdm) + return dvfs_info; + } + + return NULL; +} + +/** + * _volt_to_opp() - Find OPP corresponding to a given voltage + * @dev: device pointer associated with the OPP list + * @volt: voltage to search for in uV + * + * Searches for exact match in the OPP list and returns handle to the matching + * OPP if found, else returns ERR_PTR in case of error and should be handled + * using IS_ERR. If there are multiple opps with same voltage, it will return + * the first available entry. Return pointer should be checked against IS_ERR. + * + * NOTE: since this uses OPP functions, use under rcu_lock. This function also + * assumes that the cpufreq table and OPP table are in sync - any modifications + * to either should be synchronized. + */ +static struct opp *_volt_to_opp(struct device *dev, unsigned long volt) +{ + struct opp *opp = ERR_PTR(-ENODEV); + unsigned long f = 0; + + do { + opp = opp_find_freq_ceil(dev, &f); + if (IS_ERR(opp)) + break; + if (opp_get_voltage(opp) >= volt) + break; + f++; + } while (1); + + return opp; +} + +/* rest of the helper functions */ +/** + * _add_vdd_user() - Add a voltage request + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @dev: device making the request + * @volt: requested voltage in uV + * + * Adds the given device's voltage request into corresponding + * vdd's omap_vdd_dvfs_info user list (plist). This list is used + * to find the maximum voltage request for a given vdd. + * + * Returns 0 on success. + */ +static int _add_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, + struct device *dev, unsigned long volt) +{ + struct omap_vdd_user_list *user = NULL, *temp_user; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_warn(dev, "%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + spin_lock(&dvfs_info->user_lock); + plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) { + if (temp_user->dev == dev) { + user = temp_user; + break; + } + } + + if (!user) { + user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_ATOMIC); + if (!user) { + dev_err(dev, + "%s: Unable to creat a new user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + spin_unlock(&dvfs_info->user_lock); + return -ENOMEM; + } + user->dev = dev; + } else { + plist_del(&user->node, &dvfs_info->vdd_user_list); + } + + plist_node_init(&user->node, volt); + plist_add(&user->node, &dvfs_info->vdd_user_list); + + spin_unlock(&dvfs_info->user_lock); + return 0; +} + +/** + * _remove_vdd_user() - Remove a voltage request + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @dev: device making the request + * + * Removes the given device's voltage request from corresponding + * vdd's omap_vdd_dvfs_info user list (plist). + * + * Returns 0 on success. + */ +static int _remove_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, + struct device *dev) +{ + struct omap_vdd_user_list *user = NULL, *temp_user; + int ret = 0; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_err(dev, "%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + spin_lock(&dvfs_info->user_lock); + plist_for_each_entry(temp_user, &dvfs_info->vdd_user_list, node) { + if (temp_user->dev == dev) { + user = temp_user; + break; + } + } + + if (user) + plist_del(&user->node, &dvfs_info->vdd_user_list); + else { + dev_err(dev, "%s: Unable to find the user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + ret = -ENOENT; + } + + spin_unlock(&dvfs_info->user_lock); + kfree(user); + + return ret; +} + +/** + * _add_freq_request() - Add a requested device frequency + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @req_dev: device making the request + * @target_dev: target device for which frequency request is being made + * @freq: target device frequency + * + * This adds a requested frequency into target device's frequency list. + * + * Returns 0 on success. + */ +static int _add_freq_request(struct omap_vdd_dvfs_info *dvfs_info, + struct device *req_dev, struct device *target_dev, unsigned long freq) +{ + struct omap_dev_user_list *dev_user = NULL, *tmp_user; + struct omap_vdd_dev_list *temp_dev; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_warn(target_dev, "%s: VDD specified does not exist!\n", + __func__); + return -EINVAL; + } + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == target_dev) + break; + } + + if (temp_dev->dev != target_dev) { + dev_warn(target_dev, "%s: target_dev does not exist!\n", + __func__); + return -EINVAL; + } + + spin_lock(&temp_dev->user_lock); + plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) { + if (tmp_user->dev == req_dev) { + dev_user = tmp_user; + break; + } + } + + if (!dev_user) { + dev_user = kzalloc(sizeof(struct omap_dev_user_list), + GFP_ATOMIC); + if (!dev_user) { + dev_err(target_dev, + "%s: Unable to creat a new user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + spin_unlock(&temp_dev->user_lock); + return -ENOMEM; + } + dev_user->dev = req_dev; + } else { + plist_del(&dev_user->node, &temp_dev->freq_user_list); + } + + plist_node_init(&dev_user->node, freq); + plist_add(&dev_user->node, &temp_dev->freq_user_list); + spin_unlock(&temp_dev->user_lock); + return 0; +} + +/** + * _remove_freq_request() - Remove the requested device frequency + * + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @req_dev: device removing the request + * @target_dev: target device from which frequency request is being removed + * + * This removes a requested frequency from target device's frequency list. + * + * Returns 0 on success. + */ +static int _remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info, + struct device *req_dev, struct device *target_dev) +{ + struct omap_dev_user_list *dev_user = NULL, *tmp_user; + int ret = 0; + struct omap_vdd_dev_list *temp_dev; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_warn(target_dev, "%s: VDD specified does not exist!\n", + __func__); + return -EINVAL; + } + + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == target_dev) + break; + } + + if (temp_dev->dev != target_dev) { + dev_warn(target_dev, "%s: target_dev does not exist!\n", + __func__); + return -EINVAL; + } + + spin_lock(&temp_dev->user_lock); + plist_for_each_entry(tmp_user, &temp_dev->freq_user_list, node) { + if (tmp_user->dev == req_dev) { + dev_user = tmp_user; + break; + } + } + + if (dev_user) { + plist_del(&dev_user->node, &temp_dev->freq_user_list); + } else { + dev_err(target_dev, + "%s: Unable to remove the user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + ret = -EINVAL; + } + + spin_unlock(&temp_dev->user_lock); + kfree(dev_user); + + return ret; +} + +/** + * _dep_scan_table() - Scan a dependency table and mark for scaling + * @dev: device requesting the dependency scan (req_dev) + * @dep_info: dependency information (contains the table) + * @main_volt: voltage dependency to search for + * + * This runs down the table provided to find the match for main_volt + * provided and sets up a scale request for the dependent domain + * for the dependent voltage. + * + * Returns 0 if all went well. + */ +static int _dep_scan_table(struct device *dev, + struct omap_vdd_dep_info *dep_info, unsigned long main_volt) +{ + struct omap_vdd_dep_volt *dep_table = dep_info->dep_table; + int i; + unsigned long dep_volt = 0; + + if (!dep_table) { + dev_err(dev, "%s: deptable not present for vdd%s\n", + __func__, dep_info->name); + return -EINVAL; + } + + /* Now scan through the the dep table for a match */ + for (i = 0; i < dep_info->nr_dep_entries; i++) { + if (dep_table[i].main_vdd_volt == main_volt) { + dep_volt = dep_table[i].dep_vdd_volt; + break; + } + } + if (!dep_volt) { + dev_warn(dev, "%s: %ld volt map missing in vdd_%s\n", + __func__, main_volt, dep_info->name); + return -EINVAL; + } + + /* populate voltdm if it is not present */ + if (!dep_info->_dep_voltdm) { + dep_info->_dep_voltdm = voltdm_lookup(dep_info->name); + if (!dep_info->_dep_voltdm) { + dev_warn(dev, "%s: unable to get vdm%s\n", + __func__, dep_info->name); + return -ENODEV; + } + } + + /* See if dep_volt is possible for the vdd*/ + i = _add_vdd_user(_voltdm_to_dvfs_info(dep_info->_dep_voltdm), + dev, dep_volt); + if (i) + dev_err(dev, "%s: Failed to add dep to domain %s volt=%ld\n", + __func__, dep_info->name, dep_volt); + return i; +} + +/** + * _dep_scan_domains() - Scan dependency domains for a device + * @dev: device requesting the scan + * @vdd: vdd_info corresponding to the device + * @main_volt: voltage to scan for + * + * Since each domain *may* have multiple dependent domains, we scan + * through each of the dependent domains and invoke _dep_scan_table to + * scan each table for dependent domain for dependency scaling. + * + * This assumes that the dependent domain information is NULL entry terminated. + * Returns 0 if all went well. + */ +static int _dep_scan_domains(struct device *dev, + struct omap_vdd_info *vdd, unsigned long main_volt) +{ + struct omap_vdd_dep_info *dep_info = vdd->dep_vdd_info; + int ret = 0, r; + + if (!dep_info) { + dev_dbg(dev, "%s: No dependent VDD\n", __func__); + return 0; + } + + /* First scan through the mydomain->dep_domain list */ + while (dep_info->nr_dep_entries) { + r = _dep_scan_table(dev, dep_info, main_volt); + /* Store last failed value */ + ret = (r) ? r : ret; + dep_info++; + } + + return ret; +} + +/** + * _dep_scale_domains() - Cause a scale of all dependent domains + * @req_dev: device requesting the scale + * @req_vdd: vdd_info corresponding to the requesting device. + * + * This walks through every dependent domain and triggers a scale + * It is assumed that the corresponding scale handling for the + * domain translates this to freq and voltage scale operations as + * needed. + * + * Note: This is uses _dvfs_scale and one should be careful not to + * create a circular depedency (e.g. vdd_mpu->vdd_core->vdd->mpu) + * which can create deadlocks. No protection is provided to prevent + * this condition and a tree organization is assumed. + * + * Returns 0 if all went fine. + */ +static int _dep_scale_domains(struct device *req_dev, + struct omap_vdd_info *req_vdd) +{ + struct omap_vdd_dep_info *dep_info = req_vdd->dep_vdd_info; + int ret = 0, r; + + if (!dep_info) { + dev_dbg(req_dev, "%s: No dependent VDD\n", __func__); + return 0; + } + + /* First scan through the mydomain->dep_domain list */ + while (dep_info->nr_dep_entries) { + struct voltagedomain *tvoltdm = dep_info->_dep_voltdm; + + r = 0; + /* Scale it only if I have a voltdm mapped up for the dep */ + if (tvoltdm) { + struct omap_vdd_dvfs_info *tdvfs_info; + struct device *target_dev; + tdvfs_info = _voltdm_to_dvfs_info(tvoltdm); + if (!tdvfs_info) { + dev_warn(req_dev, "%s: no dvfs_info\n", + __func__); + goto next; + } + target_dev = _dvfs_info_to_dev(tdvfs_info); + if (!target_dev) { + dev_warn(req_dev, "%s: no target_dev\n", + __func__); + goto next; + } + r = _dvfs_scale(req_dev, target_dev, tdvfs_info); +next: + if (r) + dev_err(req_dev, "%s: dvfs_scale to %s =%d\n", + __func__, dev_name(target_dev), r); + } + /* Store last failed value */ + ret = (r) ? r : ret; + dep_info++; + } + + return ret; +} + +/** + * _dvfs_scale() : Scale the devices associated with a voltage domain + * @req_dev: Device requesting the scale + * @target_dev: Device requesting to be scaled + * @tdvfs_info: omap_vdd_dvfs_info pointer for the target domain + * + * This runs through the list of devices associated with the + * voltage domain and scales the device rates to the one requested + * by the user or those corresponding to the new voltage of the + * voltage domain. Target voltage is the highest voltage in the vdd_user_list. + * + * Returns 0 on success else the error value. + */ +static int _dvfs_scale(struct device *req_dev, struct device *target_dev, + struct omap_vdd_dvfs_info *tdvfs_info) +{ + unsigned long curr_volt, new_volt; + int volt_scale_dir = DVFS_VOLT_SCALE_DOWN; + struct omap_vdd_dev_list *temp_dev; + struct plist_node *node; + int ret = 0; + struct voltagedomain *voltdm; + struct omap_vdd_info *vdd; + + voltdm = tdvfs_info->voltdm; + if (IS_ERR_OR_NULL(voltdm)) { + dev_err(target_dev, "%s: bad voltdm\n", __func__); + return -EINVAL; + } + vdd = voltdm->vdd; + + /* Find the highest voltage being requested */ + node = plist_last(&tdvfs_info->vdd_user_list); + new_volt = node->prio; + + curr_volt = omap_vp_get_curr_volt(voltdm); + if (!curr_volt) + curr_volt = omap_voltage_get_nom_volt(voltdm); + + /* Disable smartreflex module across voltage and frequency scaling */ + omap_sr_disable(voltdm); + + if (curr_volt == new_volt) { + volt_scale_dir = DVFS_VOLT_SCALE_NONE; + } else if (curr_volt < new_volt) { + ret = voltdm_scale(voltdm, new_volt); + if (ret) { + dev_err(target_dev, + "%s: Unable to scale the %s to %ld volt\n", + __func__, voltdm->name, new_volt); + goto out; + } + volt_scale_dir = DVFS_VOLT_SCALE_UP; + } + + /* if we fail scale for dependent domains, go back to prev state */ + ret = _dep_scan_domains(target_dev, vdd, new_volt); + if (ret) { + dev_err(target_dev, + "%s: Error in scan domains for vdd_%s\n", + __func__, voltdm->name); + goto fail; + } + + /* unless we are moving down, scale dependents before we shift freq */ + if (!(DVFS_VOLT_SCALE_DOWN == volt_scale_dir)) { + ret = _dep_scale_domains(target_dev, vdd); + if (ret) { + dev_err(target_dev, + "%s: Error(%d)scale dependent with %ld volt\n", + __func__, ret, new_volt); + goto fail; + } + } + + /* Move all devices in list to the required frequencies */ + list_for_each_entry(temp_dev, &tdvfs_info->dev_list, node) { + struct device *dev; + struct opp *opp; + unsigned long freq = 0; + int r; + + dev = temp_dev->dev; + if (!plist_head_empty(&temp_dev->freq_user_list)) { + node = plist_last(&temp_dev->freq_user_list); + freq = node->prio; + } else { + /* dep domain? we'd probably have a voltage request */ + rcu_read_lock(); + opp = _volt_to_opp(dev, new_volt); + if (!IS_ERR(opp)) + freq = opp_get_freq(opp); + rcu_read_unlock(); + if (!freq) + continue; + } + + if (freq == clk_get_rate(temp_dev->clk)) { + dev_dbg(dev, "%s: Already at the requested" + "rate %ld\n", __func__, freq); + continue; + } + + r = clk_set_rate(temp_dev->clk, freq); + if (r < 0) { + dev_err(dev, "%s: clk set rate frq=%ld failed(%d)\n", + __func__, freq, r); + ret = r; + } + } + + if (ret) + goto fail; + + if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir) { + voltdm_scale(voltdm, new_volt); + _dep_scale_domains(target_dev, vdd); + } + + /* All clear.. go out gracefully */ + goto out; + +fail: + pr_warning("%s: domain%s: No clean recovery available! could be bad!\n", + __func__, voltdm->name); +out: + /* Re-enable Smartreflex module */ + omap_sr_enable(voltdm); + + return ret; +} + +/* Public functions */ + +/** + * omap_device_scale() - Set a new rate at which the device is to operate + * @req_dev: pointer to the device requesting the scaling. + * @target_dev: pointer to the device that is to be scaled + * @rate: the rnew rate for the device. + * + * This API gets the device opp table associated with this device and + * tries putting the device to the requested rate and the voltage domain + * associated with the device to the voltage corresponding to the + * requested rate. Since multiple devices can be assocciated with a + * voltage domain this API finds out the possible voltage the + * voltage domain can enter and then decides on the final device + * rate. + * + * Return 0 on success else the error value + */ +int omap_device_scale(struct device *req_dev, struct device *target_dev, + unsigned long rate) +{ + struct opp *opp; + unsigned long volt, freq = rate; + struct omap_vdd_dvfs_info *tdvfs_info; + struct platform_device *pdev; + struct omap_device *od; + int ret = 0; + + pdev = container_of(target_dev, struct platform_device, dev); + if (IS_ERR_OR_NULL(pdev)) { + pr_err("%s: pdev is null!\n", __func__); + return -EINVAL; + } + + od = container_of(pdev, struct omap_device, pdev); + if (IS_ERR_OR_NULL(od)) { + pr_err("%s: od is null!\n", __func__); + return -EINVAL; + } + + /* Lock me to ensure cross domain scaling is secure */ + mutex_lock(&omap_dvfs_lock); + + rcu_read_lock(); + opp = opp_find_freq_ceil(target_dev, &freq); + if (IS_ERR(opp)) { + rcu_read_unlock(); + dev_err(target_dev, "%s: Unable to find OPP for freq%ld\n", + __func__, rate); + ret = -ENODEV; + goto out; + } + volt = opp_get_voltage(opp); + rcu_read_unlock(); + + tdvfs_info = _dev_to_dvfs_info(target_dev); + if (IS_ERR_OR_NULL(tdvfs_info)) { + dev_err(target_dev, "%s: (req=%s) no vdd![f=%ld, v=%ld]\n", + __func__, dev_name(req_dev), freq, volt); + ret = -ENODEV; + goto out; + } + + ret = _add_freq_request(tdvfs_info, req_dev, target_dev, freq); + if (ret) { + dev_err(target_dev, "%s: freqadd(%s) failed %d[f=%ld, v=%ld]\n", + __func__, dev_name(req_dev), ret, freq, volt); + goto out; + } + + ret = _add_vdd_user(tdvfs_info, req_dev, volt); + if (ret) { + dev_err(target_dev, "%s: vddadd(%s) failed %d[f=%ld, v=%ld]\n", + __func__, dev_name(req_dev), ret, freq, volt); + _remove_freq_request(tdvfs_info, req_dev, + target_dev); + goto out; + } + + /* Do the actual scaling */ + ret = _dvfs_scale(req_dev, target_dev, tdvfs_info); + if (ret) { + dev_err(target_dev, "%s: scale by %s failed %d[f=%ld, v=%ld]\n", + __func__, dev_name(req_dev), ret, freq, volt); + _remove_freq_request(tdvfs_info, req_dev, + target_dev); + _remove_vdd_user(tdvfs_info, target_dev); + /* Fall through */ + } + /* Fall through */ +out: + mutex_unlock(&omap_dvfs_lock); + return ret; +} +EXPORT_SYMBOL(omap_device_scale); + +/** + * omap_dvfs_register_device - Add a parent device into dvfs managed list + * @dev: Device to be added + * @voltdm_name: Name of the voltage domain for the device + * @clk_name: Name of the clock for the device + * + * This function adds a given device into user_list of corresponding + * vdd's omap_vdd_dvfs_info strucure. This list is traversed to scale + * frequencies of all the devices on a given vdd. + * + * Returns 0 on success. + */ +int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name, + char *clk_name) +{ + struct omap_vdd_dev_list *temp_dev; + struct omap_vdd_dvfs_info *dvfs_info; + struct clk *clk = NULL; + struct voltagedomain *voltdm; + int ret = 0; + + if (!voltdm_name) { + dev_err(dev, "%s: Bad voltdm name!\n", __func__); + return -EINVAL; + } + if (!clk_name) { + dev_err(dev, "%s: Bad clk name!\n", __func__); + return -EINVAL; + } + + /* Lock me to secure structure changes */ + mutex_lock(&omap_dvfs_lock); + + voltdm = voltdm_lookup(voltdm_name); + if (!voltdm) { + dev_warn(dev, "%s: unable to find voltdm %s!\n", + __func__, voltdm_name); + ret = -EINVAL; + goto out; + } + dvfs_info = _voltdm_to_dvfs_info(voltdm); + if (!dvfs_info) { + dvfs_info = kzalloc(sizeof(struct omap_vdd_dvfs_info), + GFP_KERNEL); + if (!dvfs_info) { + dev_warn(dev, "%s: unable to alloc memory!\n", + __func__); + ret = -ENOMEM; + goto out; + } + dvfs_info->voltdm = voltdm; + + /* Init the plist */ + spin_lock_init(&dvfs_info->user_lock); + plist_head_init(&dvfs_info->vdd_user_list, + &dvfs_info->user_lock); + /* Init the device list */ + INIT_LIST_HEAD(&dvfs_info->dev_list); + + list_add(&dvfs_info->node, &omap_dvfs_info_list); + } + + /* If device already added, we dont need to do more.. */ + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == dev) + goto out; + } + + temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL); + if (!temp_dev) { + dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + ret = -ENOMEM; + goto out; + } + + clk = clk_get(dev, clk_name); + if (IS_ERR_OR_NULL(clk)) { + dev_warn(dev, "%s: Bad clk pointer!\n", __func__); + kfree(temp_dev); + ret = -EINVAL; + goto out; + } + + /* Initialize priority ordered list */ + spin_lock_init(&temp_dev->user_lock); + plist_head_init(&temp_dev->freq_user_list, &temp_dev->user_lock); + + temp_dev->dev = dev; + temp_dev->clk = clk; + list_add_tail(&temp_dev->node, &dvfs_info->dev_list); + + /* Fall through */ +out: + mutex_unlock(&omap_dvfs_lock); + return ret; +} diff --git a/arch/arm/mach-omap2/dvfs.h b/arch/arm/mach-omap2/dvfs.h new file mode 100644 index 0000000..da85c6d --- /dev/null +++ b/arch/arm/mach-omap2/dvfs.h @@ -0,0 +1,38 @@ +/* + * OMAP3/OMAP4 DVFS Management Routines + * + * Author: Vishwanath BS <vishwanath.bs@ti.com> + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Vishwanath BS <vishwanath.bs@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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_DVFS_H +#define __ARCH_ARM_MACH_OMAP2_DVFS_H +#include <plat/omap_hwmod.h> +#include "voltage.h" + +#ifdef CONFIG_PM +int omap_dvfs_register_device(struct device *dev, char *voltdm_name, + char *clk_name); +int omap_device_scale(struct device *req_dev, struct device *target_dev, + unsigned long rate); +#else +static inline int omap_dvfs_register_device(struct omap_hwmod *oh, + struct device *dev) +static inline int omap_dvfs_register_device(struct device *dev, + char *voltdm_name, char *clk_name) +{ + return -EINVAL; +} +static inline int omap_device_scale(struct device *req_dev, + struct device *target_dev, unsigned long rate) +{ + return -EINVAL; +} +#endif +#endif diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index b2f30be..af991ff 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -145,6 +145,7 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, int power_on, int vdd) { u32 reg; + unsigned long timeout; if (power_on) { reg = omap4_ctrl_pad_readl(control_pbias_offset); @@ -157,9 +158,15 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, OMAP4_MMC1_PWRDNZ_MASK | OMAP4_USBC1_ICUSB_PWRDNZ_MASK); omap4_ctrl_pad_writel(reg, control_pbias_offset); - /* 4 microsec delay for comparator to generate an error*/ - udelay(4); - reg = omap4_ctrl_pad_readl(control_pbias_offset); + + timeout = jiffies + msecs_to_jiffies(5); + do { + reg = omap4_ctrl_pad_readl(control_pbias_offset); + if (!(reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK)) + break; + usleep_range(100, 200); + } while (!time_after(jiffies, timeout)); + if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) { pr_err("Pbias Voltage is not same as LDO\n"); /* Caution : On VMODE_ERROR Power Down MMC IO */ @@ -331,9 +338,19 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, if (c->no_off) mmc->slots[0].no_off = 1; + if (c->no_off_init) + mmc->slots[0].no_regulator_off_init = c->no_off_init; + if (c->vcc_aux_disable_is_sleep) mmc->slots[0].vcc_aux_disable_is_sleep = 1; + if (cpu_is_omap44xx()) { + if (omap_rev() > OMAP4430_REV_ES1_0) + mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET; + if (c->mmc >= 3 && c->mmc <= 5) + mmc->slots[0].features |= HSMMC_HAS_48MHZ_MASTER_CLK; + } + /* * NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index f119348..f757e78 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -18,6 +18,7 @@ struct omap2_hsmmc_info { bool nonremovable; /* Nonremovable e.g. eMMC */ bool power_saving; /* Try to sleep or power off when possible */ bool no_off; /* power_saving and power is not to go off */ + bool no_off_init; /* no power off when not in MMC sleep state */ bool vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 2537090..cd3c00e 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -331,8 +331,13 @@ static void __init omap3_check_revision(void) static void __init omap4_check_revision(void) { u32 idcode; - u16 hawkeye; u8 rev; + /* + * NOTE: OMAP4460+ uses ramp system for identification and hawkeye + * variable is reused for the same. Since the values are unique + * we continue to use the current system + */ + u16 hawkeye; /* * The IC rev detection is done with hawkeye and rev. @@ -344,10 +349,10 @@ static void __init omap4_check_revision(void) rev = (idcode >> 28) & 0xf; /* - * Few initial ES2.0 samples IDCODE is same as ES1.0 + * Few initial 4430 ES2.0 samples IDCODE is same as ES1.0 * Use ARM register to detect the correct ES version */ - if (!rev) { + if (!rev && (hawkeye != 0xb94e)) { idcode = read_cpuid(CPUID_ID); rev = (idcode & 0xf) - 1; } @@ -377,6 +382,15 @@ static void __init omap4_check_revision(void) omap_chip.oc |= CHIP_IS_OMAP4430ES2_2; } break; + case 0xb94e: + switch (rev) { + case 0: + default: + omap_revision = OMAP4460_REV_ES1_0; + omap_chip.oc |= CHIP_IS_OMAP4460ES1_0; + break; + } + break; default: /* Unknown default to latest silicon rev as default */ omap_revision = OMAP4430_REV_ES2_2; diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-omap2/include/mach/dmm.h new file mode 100644 index 0000000..e847a71 --- /dev/null +++ b/arch/arm/mach-omap2/include/mach/dmm.h @@ -0,0 +1,148 @@ +/* + * dmm.h + * + * DMM driver support functions for TI DMM-TILER hardware block. + * + * Author: David Sin <davidsin@ti.com> + * + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DMM_H +#define DMM_H + +#define DMM_BASE 0x4E000000 +#define DMM_SIZE 0x800 + +#define DMM_REVISION 0x000 +#define DMM_HWINFO 0x004 +#define DMM_LISA_HWINFO 0x008 +#define DMM_DMM_SYSCONFIG 0x010 +#define DMM_LISA_LOCK 0x01C +#define DMM_LISA_MAP__0 0x040 +#define DMM_LISA_MAP__1 0x044 +#define DMM_TILER_HWINFO 0x208 +#define DMM_TILER_OR__0 0x220 +#define DMM_TILER_OR__1 0x224 +#define DMM_PAT_HWINFO 0x408 +#define DMM_PAT_GEOMETRY 0x40C +#define DMM_PAT_CONFIG 0x410 +#define DMM_PAT_VIEW__0 0x420 +#define DMM_PAT_VIEW__1 0x424 +#define DMM_PAT_VIEW_MAP__0 0x440 +#define DMM_PAT_VIEW_MAP_BASE 0x460 +#define DMM_PAT_IRQ_EOI 0x478 +#define DMM_PAT_IRQSTATUS_RAW 0x480 +#define DMM_PAT_IRQSTATUS 0x490 +#define DMM_PAT_IRQENABLE_SET 0x4A0 +#define DMM_PAT_IRQENABLE_CLR 0x4B0 +#define DMM_PAT_STATUS__0 0x4C0 +#define DMM_PAT_STATUS__1 0x4C4 +#define DMM_PAT_STATUS__2 0x4C8 +#define DMM_PAT_STATUS__3 0x4CC +#define DMM_PAT_DESCR__0 0x500 +#define DMM_PAT_AREA__0 0x504 +#define DMM_PAT_CTRL__0 0x508 +#define DMM_PAT_DATA__0 0x50C +#define DMM_PEG_HWINFO 0x608 +#define DMM_PEG_PRIO 0x620 +#define DMM_PEG_PRIO_PAT 0x640 + +/** + * PAT refill programming mode. + */ +enum pat_mode { + MANUAL, + AUTO +}; + +/** + * Area definition for DMM physical address translator. + */ +struct pat_area { + s32 x0:8; + s32 y0:8; + s32 x1:8; + s32 y1:8; +}; + +/** + * DMM physical address translator control. + */ +struct pat_ctrl { + s32 start:4; + s32 dir:4; + s32 lut_id:8; + s32 sync:12; + s32 ini:4; +}; + +/** + * PAT descriptor. + */ +struct pat { + struct pat *next; + struct pat_area area; + struct pat_ctrl ctrl; + u32 data; +}; + +/** + * DMM device data + */ +struct dmm { + void __iomem *base; +}; + +/** + * Create and initialize the physical address translator. + * @param id PAT id + * @return pointer to device data + */ +struct dmm *dmm_pat_init(u32 id); + +/** + * Program the physical address translator. + * @param dmm Device data + * @param desc PAT descriptor + * @param mode programming mode + * @return an error status. + */ +s32 dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum pat_mode mode); + +/** + * Clean up the physical address translator. + * @param dmm Device data + * @return an error status. + */ +void dmm_pat_release(struct dmm *dmm); + +#endif diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h new file mode 100644 index 0000000..66f31c3 --- /dev/null +++ b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h @@ -0,0 +1,41 @@ +/* + * OMAP WakeupGen header file + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Written by Santosh Shilimkar <santosh.shilimkar@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. + */ +#ifndef OMAP_ARCH_WAKEUPGEN_H +#define OMAP_ARCH_WAKEUPGEN_H + +#define OMAP_WKG_CONTROL_0 0x00 +#define OMAP_WKG_ENB_A_0 0x10 +#define OMAP_WKG_ENB_B_0 0x14 +#define OMAP_WKG_ENB_C_0 0x18 +#define OMAP_WKG_ENB_D_0 0x1c +#define OMAP_WKG_ENB_SECURE_A_0 0x20 +#define OMAP_WKG_ENB_SECURE_B_0 0x24 +#define OMAP_WKG_ENB_SECURE_C_0 0x28 +#define OMAP_WKG_ENB_SECURE_D_0 0x2c +#define OMAP_WKG_ENB_A_1 0x410 +#define OMAP_WKG_ENB_B_1 0x414 +#define OMAP_WKG_ENB_C_1 0x418 +#define OMAP_WKG_ENB_D_1 0x41c +#define OMAP_WKG_ENB_SECURE_A_1 0x420 +#define OMAP_WKG_ENB_SECURE_B_1 0x424 +#define OMAP_WKG_ENB_SECURE_C_1 0x428 +#define OMAP_WKG_ENB_SECURE_D_1 0x42c +#define OMAP_AUX_CORE_BOOT_0 0x800 +#define OMAP_AUX_CORE_BOOT_1 0x804 +#define OMAP_PTMSYNCREQ_MASK 0xc00 +#define OMAP_PTMSYNCREQ_EN 0xc04 +#define OMAP_TIMESTAMPCYCLELO 0xc08 +#define OMAP_TIMESTAMPCYCLEHI 0xc0c + +extern int __init omap_wakeupgen_init(void); +extern void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set); +extern void omap_wakeupgen_save(void); +#endif diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h index e4bd87619..8ebb641 100644 --- a/arch/arm/mach-omap2/include/mach/omap4-common.h +++ b/arch/arm/mach-omap2/include/mach/omap4-common.h @@ -13,31 +13,109 @@ #ifndef OMAP_ARCH_OMAP4_COMMON_H #define OMAP_ARCH_OMAP4_COMMON_H +#include <asm/proc-fns.h> /* - * wfi used in low power code. Directly opcode is used instead - * of instruction to avoid mulit-omap build break + * Secure low power context save/restore API index */ -#ifdef CONFIG_THUMB2_KERNEL -#define do_wfi() __asm__ __volatile__ ("wfi" : : : "memory") -#else -#define do_wfi() \ - __asm__ __volatile__ (".word 0xe320f003" : : : "memory") -#endif +#define HAL_SAVESECURERAM_INDEX 0x1a +#define HAL_SAVEHW_INDEX 0x1b +#define HAL_SAVEALL_INDEX 0x1c +#define HAL_SAVEGIC_INDEX 0x1d +#define PPA_SERVICE_NS_SMP 0x25 +/* + * Secure HAL API flags + */ +#define FLAG_START_CRITICAL 0x4 +#define FLAG_IRQFIQ_MASK 0x3 +#define FLAG_IRQ_ENABLE 0x2 +#define FLAG_FIQ_ENABLE 0x1 +#define NO_FLAG 0x0 + +#ifndef __ASSEMBLER__ #ifdef CONFIG_CACHE_L2X0 -extern void __iomem *l2cache_base; +extern void __iomem *omap4_get_l2cache_base(void); #endif -extern void __iomem *gic_dist_base_addr; +#ifdef CONFIG_SMP +extern void __iomem *omap4_get_scu_base(void); +#else +static inline void __iomem *omap4_get_scu_base(void) +{ + return NULL; +} +#endif +extern void __iomem *omap4_get_gic_dist_base(void); +extern void __iomem *omap4_get_gic_cpu_base(void); +extern void __iomem *omap4_get_sar_ram_base(void); +extern dma_addr_t omap4_secure_ram_phys; extern void __init gic_init_irq(void); +extern void gic_cpu_enable(void); +extern void gic_cpu_disable(void); +extern void gic_dist_enable(void); +extern void gic_dist_disable(void); extern void omap_smc1(u32 fn, u32 arg); +/* + * Read MPIDR: Multiprocessor affinity register + */ +static inline unsigned int hard_smp_processor_id(void) +{ + unsigned int cpunum; + + asm volatile ( + "mrc p15, 0, %0, c0, c0, 5\n" + : "=r" (cpunum)); + return cpunum &= 0x0f; +} + #ifdef CONFIG_SMP /* Needed for secondary core boot */ extern void omap_secondary_startup(void); extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); extern void omap_auxcoreboot_addr(u32 cpu_addr); extern u32 omap_read_auxcoreboot0(void); -#endif -#endif + +#ifdef CONFIG_PM +extern int omap4_mpuss_init(void); +extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); +extern void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state); +extern void omap4_cpu_resume(void); +extern u32 omap_smc2(u32 id, u32 falg, u32 pargs); +extern u32 omap4_secure_dispatcher(u32 idx, u32 flag, u32 nargs, + u32 arg1, u32 arg2, u32 arg3, u32 arg4); +#else +static inline int omap4_enter_lowpower(unsigned int cpu, + unsigned int power_state) +{ + cpu_do_idle(); + return 0; +} + +static inline int omap4_mpuss_init(void) +{ + return 0; +} + +static inline void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state) +{ +} + +static inline void omap4_cpu_resume(void) +{ +} + +static inline u32 omap_smc2(u32 id, u32 falg, u32 pargs) +{ + return 0; +} +static inline u32 omap4_secure_dispatcher(u32 idx, u32 flag, u32 nargs, + u32 arg1, u32 arg2, u32 arg3, u32 arg4) +{ + return 0; +} +#endif /* CONFIG_PM */ +#endif /* CONFIG_SMP */ +#endif /* __ASSEMBLER__ */ +#endif /* OMAP_ARCH_OMAP4_COMMON_H */ diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-omap2/include/mach/tiler.h new file mode 100644 index 0000000..1bdc6bd --- /dev/null +++ b/arch/arm/mach-omap2/include/mach/tiler.h @@ -0,0 +1,515 @@ +/* + * tiler.h + * + * TILER driver support functions for TI TILER hardware block. + * + * Authors: Lajos Molnar <molnar@ti.com> + * David Sin <davidsin@ti.com> + * + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TILER_H +#define TILER_H + +#include <linux/mm.h> +#include <linux/scatterlist.h> + +/* + * ----------------------------- API Definitions ----------------------------- + */ + +/* return true if physical address is in the tiler container */ +bool is_tiler_addr(u32 phys); + +enum tiler_fmt { + TILFMT_MIN = -2, + TILFMT_INVALID = -2, + TILFMT_NONE = -1, + TILFMT_8BIT = 0, + TILFMT_16BIT = 1, + TILFMT_32BIT = 2, + TILFMT_PAGE = 3, + TILFMT_MAX = 3, + TILFMT_8AND16 = 4, /* used to mark NV12 reserve block */ +}; + +/* tiler block info */ +struct tiler_block_t { + u32 phys; /* system space (L3) tiler addr */ + u32 width; /* width */ + u32 height; /* height */ + u32 key; /* secret key */ + u32 id; /* unique block ID */ +}; + +/* tiler (image/video frame) view */ +struct tiler_view_t { + u32 tsptr; /* tiler space addr */ + u32 width; /* width */ + u32 height; /* height */ + u32 bpp; /* bytes per pixel */ + s32 h_inc; /* horizontal increment */ + s32 v_inc; /* vertical increment */ +}; + +/* get the tiler format for a physical address or TILFMT_INVALID */ +enum tiler_fmt tiler_fmt(u32 phys); + +/* get the modified (1 for page mode) bytes-per-pixel for a tiler block */ +u32 tiler_bpp(const struct tiler_block_t *b); + +/* get tiler block physical stride */ +u32 tiler_pstride(const struct tiler_block_t *b); + +/* get tiler block virtual stride */ +static inline u32 tiler_vstride(const struct tiler_block_t *b) +{ + return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width); +} + +/* returns the virtual size of the block (for mmap) */ +static inline u32 tiler_size(const struct tiler_block_t *b) +{ + return b->height * tiler_vstride(b); +} + +/* Event types */ +#define TILER_DEVICE_CLOSE 0 + +/** + * Registers a notifier block with TILER driver. + * + * @param nb notifier_block + * + * @return error status + */ +s32 tiler_reg_notifier(struct notifier_block *nb); + +/** + * Un-registers a notifier block with TILER driver. + * + * @param nb notifier_block + * + * @return error status + */ +s32 tiler_unreg_notifier(struct notifier_block *nb); + +/** + * Get the physical address for a given user va. + * + * @param usr user virtual address + * + * @return valid pa or 0 for error + */ +u32 tiler_virt2phys(u32 usr); + +/** + * Reserves a 1D or 2D TILER block area and memory for the + * current process with group ID 0. + * + * @param blk pointer to tiler block data. This must be set up ('phys' member + * must be 0) with the tiler block information. 'height' must be 1 + * for 1D block. + * @param fmt TILER block format + * + * @return error status + */ +s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt); + +/** + * Reserves a 1D or 2D TILER block area and memory for a set process and group + * ID. + * + * @param blk pointer to tiler block data. This must be set up ('phys' member + * must be 0) with the tiler block information. 'height' must be 1 + * for 1D block. + * @param fmt TILER block format + * @param gid group ID + * @param pid process ID + * + * @return error status + */ +s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, + u32 gid, pid_t pid); + +/** + * Mmaps a portion of a tiler block to a virtual address. Use this method in + * your driver's mmap function to potentially combine multiple tiler blocks as + * one virtual buffer. + * + * @param blk pointer to tiler block data + * @param offs offset from where to map (must be page aligned) + * @param size size of area to map (must be page aligned) + * @param vma VMM memory area to map to + * @param voffs offset (from vm_start) in the VMM memory area to start + * mapping at + * + * @return error status + */ +s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size, + struct vm_area_struct *vma, u32 voffs); + +/** + * Ioremaps a portion of a tiler block. Use this method in your driver instead + * of ioremap to potentially combine multiple tiler blocks as one virtual + * buffer. + * + * @param blk pointer to tiler block data + * @param offs offset from where to map (must be page aligned) + * @param size size of area to map (must be page aligned) + * @param addr virtual address + * @param mtype ioremap memory type (e.g. MT_DEVICE) + * + * @return error status + */ +s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32 addr, + u32 mtype); + +/** + * Maps an existing buffer to a 1D or 2D TILER area for the + * current process with group ID 0. + * + * Currently, only 1D area mapping is supported. + * + * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped + * into tiler container. + * + * @param blk pointer to tiler block data. This must be set up + * ('phys' member must be 0) with the tiler block + * information. 'height' must be 1 for 1D block. + * @param fmt TILER format + * @param usr_addr user space address of existing buffer. + * + * @return error status + */ +s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr); + +/** + * Maps an existing buffer to a 1D or 2D TILER area for a set process and group + * ID. + * + * Currently, only 1D area mapping is supported. + * + * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped + * into tiler container. + * + * @param blk pointer to tiler block data. This must be set up + * ('phys' member must be 0) with the tiler block + * information. 'height' must be 1 for 1D block. + * @param fmt TILER format + * @param gid group ID + * @param pid process ID + * @param usr_addr user space address of existing buffer. + * + * @return error status + */ +s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, + u32 gid, pid_t pid, u32 usr_addr); + +/** + * Frees TILER memory. Since there may be multiple references for the same area + * if duplicated by tiler_dup, the area is only actually freed if all references + * have been freed. + * + * @param blk pointer to a tiler block data as filled by tiler_alloc, + * tiler_map or tiler_dup. 'phys' and 'id' members will be set to + * 0 on success. + */ +void tiler_free(struct tiler_block_t *blk); + +/** + * Reserves tiler area for n identical blocks for the current process. Use this + * method to get optimal placement of multiple identical tiler blocks; however, + * it may not reserve area if tiler_alloc is equally efficient. + * + * @param n number of identical set of blocks + * @param fmt TILER format + * @param width block width + * @param height block height (must be 1 for 1D) + */ +void tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height); + +/** + * Reserves tiler area for n identical blocks. Use this method to get optimal + * placement of multiple identical tiler blocks; however, it may not reserve + * area if tiler_alloc is equally efficient. + * + * @param n number of identical set of blocks + * @param fmt TILER bit mode + * @param width block width + * @param height block height (must be 1 for 1D) + * @param gid group ID + * @param pid process ID + */ +void tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height, + u32 gid, pid_t pid); + +/** + * Reserves tiler area for n identical NV12 blocks for the current process. Use + * this method to get optimal placement of multiple identical NV12 tiler blocks; + * however, it may not reserve area if tiler_alloc is equally efficient. + * + * @param n number of identical set of blocks + * @param width block width (Y) + * @param height block height (Y) + */ +void tiler_reserve_nv12(u32 n, u32 width, u32 height); + +/** + * Reserves tiler area for n identical NV12 blocks. Use this method to get + * optimal placement of multiple identical NV12 tiler blocks; however, it may + * not reserve area if tiler_alloc is equally efficient. + * + * @param n number of identical set of blocks + * @param width block width (Y) + * @param height block height (Y) + * @param gid group ID + * @param pid process ID + */ +void tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 gid, pid_t pid); + +/** + * Create a view based on a tiler address and width and height + * + * This method should only be used as a last resort, e.g. if tilview object + * cannot be passed because of incoherence with other view 2D objects that must + * be supported. + * + * @param view Pointer to a view where the information will be stored + * @param ssptr MUST BE a tiler address + * @param width view width + * @param height view height + */ +void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height); + +/** + * Obtains the view information for a tiler block + * + * @param view Pointer to a view where the information will be stored + * @param blk Pointer to an existing allocated tiler block + */ +void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk); + +/** + * Crops a tiler view to a rectangular portion. Crop area must be fully within + * the orginal tiler view: 0 <= left <= left + width <= view->width, also: + * 0 <= top <= top + height <= view->height. + * + * @param view Pointer to tiler view to be cropped + * @param left x of top-left corner + * @param top y of top-left corner + * @param width crop width + * @param height crop height + * + * @return error status. The view will be reduced to the crop region if the + * crop region is correct. Otherwise, no modifications are made. + */ +s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width, + u32 height); + +/** + * Rotates a tiler view clockwise by a specified degree. + * + * @param view Pointer to tiler view to be cropped + * @param rotate Degree of rotation (clockwise). Must be a multiple of + * 90. + * @return error status. View is not modified on error; otherwise, it is + * updated in place. + */ +s32 tilview_rotate(struct tiler_view_t *view, s32 rotation); + +/** + * Mirrors a tiler view horizontally and/or vertically. + * + * @param view Pointer to tiler view to be cropped + * @param flip_x Mirror horizontally (left-to-right) + * @param flip_y Mirror vertically (top-to-bottom) + * + * @return error status. View is not modified on error; otherwise, it is + * updated in place. + */ +s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y); + +/* + * -------------------- TILER hooks for ION/HWC migration -------------------- + */ + +/* type of tiler memory */ +enum tiler_memtype { + TILER_MEM_ALLOCED, /* tiler allocated the memory */ + TILER_MEM_GOT_PAGES, /* tiler used get_user_pages */ + TILER_MEM_USING, /* tiler is using the pages */ +}; + +/* physical pages to pin - mem must be kmalloced */ +struct tiler_pa_info { + u32 num_pg; /* number of pages in page-list */ + u32 *mem; /* list of phys page addresses */ + enum tiler_memtype memtype; /* how we got physical pages */ +}; + +typedef struct mem_info *tiler_blk_handle; + +/** + * Allocate a 1D area of container space in the Tiler + * + * @param pa ptr to tiler_pa_info structure + * + * @return handle Handle to tiler block information. NULL on error. + * + * NOTE: this will take ownership pa->mem (will free it) + * + */ +tiler_blk_handle tiler_map_1d_block(struct tiler_pa_info *pa); + +/** + * Allocate an area of container space in the Tiler + * + * @param fmt Tiler bpp mode + * @param width Width in pixels + * @param height Height in pixels + * @param ssptr Value of tiler physical address of allocation + * + * @return handle Handle to tiler block information. NULL on error. + * + * NOTE: For 1D allocations, specify the full size in the width field, and + * specify a height of 1. + */ +tiler_blk_handle tiler_alloc_block_area(enum tiler_fmt fmt, u32 width, + u32 height, u32 *ssptr); + +/** + * Free a reserved area in the Tiler + * + * @param handle Handle to tiler block information + * + */ +void tiler_free_block_area(tiler_blk_handle block); + +/** + * Pins a set of physical pages into the Tiler using the area defined in a + * handle + * + * @param handle Handle to tiler block information + * @param sg Scatterlist of physical pages + * @param nents Number of entries in scatterlist + * + * @return error status. + */ +s32 tiler_pin_block(tiler_blk_handle handle, struct scatterlist *sg, u32 nents); + +/** + * Unpins a set of physical pages from the Tiler + * + * @param handle Handle to tiler block information + * + */ +void tiler_unpin_block(tiler_blk_handle handle); + + +/** + * Gives Tiler physical address for a given tiler_blk_handle + * + * @param handle Handle to tiler block information + * + * @return phsyical address. NULL on error. + */ +u32 tiler_handle_to_phys(tiler_blk_handle handle); + +/** + * Gives memory requirements for a given container allocation + * + * @param fmt Tiler bpp mode + * @param width Width in pixels + * @param height Height in pixels + * + * @return Number of pages required. On error, returns 0 + */ +u32 tiler_memsize(enum tiler_fmt fmt, u32 width, u32 height); + +/** + * Returns virtual stride of a tiler block + * + * @param handle Handle to tiler block allocation + * + * @return Size of virtual stride + */ +u32 tiler_block_vstride(tiler_blk_handle handle); + +/* + * ---------------------------- IOCTL Definitions ---------------------------- + */ + +/* ioctls */ +#define TILIOC_GBLK _IOWR('z', 100, struct tiler_block_info) +#define TILIOC_FBLK _IOW('z', 101, struct tiler_block_info) +#define TILIOC_GSSP _IOWR('z', 102, u32) +#define TILIOC_MBLK _IOWR('z', 103, struct tiler_block_info) +#define TILIOC_UMBLK _IOW('z', 104, struct tiler_block_info) +#define TILIOC_QBUF _IOWR('z', 105, struct tiler_buf_info) +#define TILIOC_RBUF _IOWR('z', 106, struct tiler_buf_info) +#define TILIOC_URBUF _IOWR('z', 107, struct tiler_buf_info) +#define TILIOC_QBLK _IOWR('z', 108, struct tiler_block_info) +#define TILIOC_PRBLK _IOW('z', 109, struct tiler_block_info) +#define TILIOC_URBLK _IOW('z', 110, u32) + +struct area { + u16 width; + u16 height; +}; + +/* userspace tiler block info */ +struct tiler_block_info { + enum tiler_fmt fmt; + union { + struct area area; + u32 len; + } dim; + u32 stride; /* stride is not maintained for 1D blocks */ + void *ptr; /* userspace address for mapping existing buffer */ + u32 id; + u32 key; + u32 group_id; + u32 ssptr; /* physical address, may not exposed by default */ +}; + +#define TILER_MAX_NUM_BLOCKS 16 + +/* userspace tiler buffer info */ +struct tiler_buf_info { + u32 num_blocks; + struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS]; + u32 offset; + u32 length; /* also used as number of buffers for reservation */ +}; + +#endif diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 441e79d..b5c8e80 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -38,6 +38,7 @@ #include "io.h" #include <plat/omap-pm.h> +#include "voltage.h" #include "powerdomain.h" #include "clockdomain.h" @@ -355,18 +356,22 @@ void __init omap2_init_common_infrastructure(void) u8 postsetup_state; if (cpu_is_omap242x()) { + omap2xxx_voltagedomains_init(); omap2xxx_powerdomains_init(); omap2xxx_clockdomains_init(); omap2420_hwmod_init(); } else if (cpu_is_omap243x()) { + omap2xxx_voltagedomains_init(); omap2xxx_powerdomains_init(); omap2xxx_clockdomains_init(); omap2430_hwmod_init(); } else if (cpu_is_omap34xx()) { + omap3xxx_voltagedomains_init(); omap3xxx_powerdomains_init(); omap3xxx_clockdomains_init(); omap3xxx_hwmod_init(); } else if (cpu_is_omap44xx()) { + omap44xx_voltagedomains_init(); omap44xx_powerdomains_init(); omap44xx_clockdomains_init(); omap44xx_hwmod_init(); diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c index adb083e..11acc43 100644 --- a/arch/arm/mach-omap2/iommu2.c +++ b/arch/arm/mach-omap2/iommu2.c @@ -19,6 +19,7 @@ #include <linux/stringify.h> #include <plat/iommu.h> +#include <plat/omap_device.h> /* * omap2 architecture specific register bit definitions @@ -89,6 +90,7 @@ static int omap2_iommu_enable(struct iommu *obj) { u32 l, pa; unsigned long timeout; + int ret = 0; if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) return -EINVAL; @@ -97,6 +99,10 @@ static int omap2_iommu_enable(struct iommu *obj) if (!IS_ALIGNED(pa, SZ_16K)) return -EINVAL; + ret = omap_device_enable(obj->pdev); + if (ret) + return ret; + iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG); timeout = jiffies + msecs_to_jiffies(20); @@ -129,6 +135,8 @@ static int omap2_iommu_enable(struct iommu *obj) static void omap2_iommu_disable(struct iommu *obj) { + int ret = 0; + u32 l = iommu_read_reg(obj, MMU_CNTL); l &= ~MMU_CNTL_MASK; @@ -136,6 +144,8 @@ static void omap2_iommu_disable(struct iommu *obj) iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG); dev_dbg(obj->dev, "%s is shutting down\n", obj->name); + if (omap_device_shutdown(obj->pdev)) + dev_err(obj->dev, "%s err 0x%x\n", __func__, ret); } static void omap2_iommu_set_twl(struct iommu *obj, bool on) @@ -225,7 +235,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e) attr = e->mixed << 5; attr |= e->endian; attr |= e->elsz >> 3; - attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6); + attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) || + (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6); return attr; } diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 4a6ef6a..01447f6 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -71,9 +71,9 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id) mcbsp = id_to_mcbsp_ptr(id); if (fck_src_id == MCBSP_CLKS_PAD_SRC) - fck_src_name = "pad_fck"; + fck_src_name = mcbsp->pdata->clks_pad_src; else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) - fck_src_name = "prcm_fck"; + fck_src_name = mcbsp->pdata->clks_prcm_src; else return -EINVAL; @@ -129,12 +129,21 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->mcbsp_config_type = oh->class->rev; if (oh->class->rev == MCBSP_CONFIG_TYPE3) { + strcpy(pdata->clks_pad_src, "pad_clks_ck"); + strcpy(pdata->clks_prcm_src, "mcbsp2_sync_mux_ck"); + if (id == 2) /* The FIFO has 1024 + 256 locations */ pdata->buffer_size = 0x500; else /* The FIFO has 128 locations */ pdata->buffer_size = 0x80; + } else if (oh->class->rev == MCBSP_CONFIG_TYPE4) { + strcpy(pdata->clks_pad_src, "pad_clks_ck"); + strcpy(pdata->clks_prcm_src, "mcbsp2_sync_mux_ck"); + + /* The FIFO has 128 locations for all instances */ + pdata->buffer_size = 0x80; } oh_device[0] = oh; diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index a4ab1e3..c7fb22a 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -83,6 +83,9 @@ void omap_mux_write(struct omap_mux_partition *partition, u16 val, void omap_mux_write_array(struct omap_mux_partition *partition, struct omap_board_mux *board_mux) { + if (!board_mux) + return; + while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) { omap_mux_write(partition, board_mux->value, board_mux->reg_offset); @@ -906,7 +909,7 @@ static struct omap_mux *omap_mux_get_by_gpio( u16 omap_mux_get_gpio(int gpio) { struct omap_mux_partition *partition; - struct omap_mux *m; + struct omap_mux *m = NULL; list_for_each_entry(partition, &mux_partitions, node) { m = omap_mux_get_by_gpio(partition, gpio); diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h index 137f321..2132308 100644 --- a/arch/arm/mach-omap2/mux.h +++ b/arch/arm/mach-omap2/mux.h @@ -323,10 +323,12 @@ int omap3_mux_init(struct omap_board_mux *board_mux, int flags); /** * omap4_mux_init() - initialize mux system with board specific set - * @board_mux: Board specific mux table + * @board_subset: Board specific mux table + * @board_wkup_subset: Board specific mux table for wakeup instance * @flags: OMAP package type used for the board */ -int omap4_mux_init(struct omap_board_mux *board_mux, int flags); +int omap4_mux_init(struct omap_board_mux *board_subset, + struct omap_board_mux *board_wkup_subset, int flags); /** * omap_mux_init - private mux init function, do not call diff --git a/arch/arm/mach-omap2/mux44xx.c b/arch/arm/mach-omap2/mux44xx.c index 9a66445..f5a74da 100644 --- a/arch/arm/mach-omap2/mux44xx.c +++ b/arch/arm/mach-omap2/mux44xx.c @@ -1309,7 +1309,8 @@ static struct omap_ball __initdata omap4_wkup_cbl_cbs_ball[] = { #define omap4_wkup_cbl_cbs_ball NULL #endif -int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags) +int __init omap4_mux_init(struct omap_board_mux *board_subset, + struct omap_board_mux *board_wkup_subset, int flags) { struct omap_ball *package_balls_core; struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball; @@ -1347,7 +1348,7 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags) OMAP_MUX_GPIO_IN_MODE3, OMAP4_CTRL_MODULE_PAD_WKUP_MUX_PBASE, OMAP4_CTRL_MODULE_PAD_WKUP_MUX_SIZE, - omap4_wkup_muxmodes, NULL, board_subset, + omap4_wkup_muxmodes, NULL, board_wkup_subset, package_balls_wkup); return ret; diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index 4976b93..f69cd5c 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c @@ -19,7 +19,13 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> + #include <mach/omap4-common.h> +#include <mach/omap-wakeupgen.h> + +#include "powerdomain.h" +#include "clockdomain.h" int platform_cpu_kill(unsigned int cpu) { @@ -32,6 +38,12 @@ int platform_cpu_kill(unsigned int cpu) */ void platform_cpu_die(unsigned int cpu) { + unsigned int this_cpu; + static struct clockdomain *cpu1_clkdm; + + if (!cpu1_clkdm) + cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); + flush_cache_all(); dsb(); @@ -39,18 +51,26 @@ void platform_cpu_die(unsigned int cpu) * we're ready for shutdown now, so do it */ if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0) - printk(KERN_CRIT "Secure clear status failed\n"); + pr_err("Secure clear status failed\n"); for (;;) { /* - * Execute WFI + * Enter into low power state + * clear all interrupt wakeup sources */ - do_wfi(); - - if (omap_read_auxcoreboot0() == cpu) { + omap_wakeupgen_irqmask_all(cpu, 1); + gic_cpu_disable(); + omap4_enter_lowpower(cpu, PWRDM_POWER_OFF); + this_cpu = hard_smp_processor_id(); + if (omap_read_auxcoreboot0() == this_cpu) { /* * OK, proper wakeup, we're done */ + omap_wakeupgen_irqmask_all(this_cpu, 0); + gic_cpu_enable(); + + /* Restore clockdomain to hardware supervised */ + clkdm_allow_idle(cpu1_clkdm); break; } pr_debug("CPU%u: spurious wakeup call\n", cpu); diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c index 3fc5dc7..b864cd9 100644 --- a/arch/arm/mach-omap2/omap-iommu.c +++ b/arch/arm/mach-omap2/omap-iommu.c @@ -11,9 +11,12 @@ */ #include <linux/platform_device.h> +#include <linux/err.h> #include <plat/iommu.h> -#include <plat/irqs.h> +#include <plat/omap_device.h> +#include <plat/omap_hwmod.h> + struct iommu_device { resource_size_t base; @@ -21,145 +24,118 @@ struct iommu_device { struct iommu_platform_data pdata; struct resource res[2]; }; -static struct iommu_device *devices; +static struct iommu_platform_data *devices_data; static int num_iommu_devices; #ifdef CONFIG_ARCH_OMAP3 -static struct iommu_device omap3_devices[] = { +static struct iommu_platform_data omap3_devices_data[] = { { - .base = 0x480bd400, - .irq = 24, - .pdata = { - .name = "isp", - .nr_tlb_entries = 8, - .clk_name = "cam_ick", - .da_start = 0x0, - .da_end = 0xFFFFF000, - }, + .name = "isp", + .oh_name = "isp", + .nr_tlb_entries = 8, + .da_start = 0x0, + .da_end = 0xFFFFF000, }, #if defined(CONFIG_OMAP_IOMMU_IVA2) { - .base = 0x5d000000, - .irq = 28, - .pdata = { - .name = "iva2", - .nr_tlb_entries = 32, - .clk_name = "iva2_ck", - .da_start = 0x11000000, - .da_end = 0xFFFFF000, - }, + .name = "iva2", + .oh_name = "dsp", + .nr_tlb_entries = 32, + .da_start = 0x11000000, + .da_end = 0xFFFFF000, }, #endif }; -#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices) -static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES]; +#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices_data) #else -#define omap3_devices NULL +#define omap3_devices_data NULL #define NR_OMAP3_IOMMU_DEVICES 0 -#define omap3_iommu_pdev NULL #endif #ifdef CONFIG_ARCH_OMAP4 -static struct iommu_device omap4_devices[] = { +static struct iommu_platform_data omap4_devices_data[] = { { - .base = OMAP4_MMU1_BASE, - .irq = OMAP44XX_IRQ_DUCATI_MMU, - .pdata = { - .name = "ducati", - .nr_tlb_entries = 32, - .clk_name = "ducati_ick", - .da_start = 0x0, - .da_end = 0xFFFFF000, - }, + .name = "ducati", + .oh_name = "ipu", + .nr_tlb_entries = 32, + .da_start = 0x0, + .da_end = 0xFFFFF000, }, -#if defined(CONFIG_MPU_TESLA_IOMMU) { - .base = OMAP4_MMU2_BASE, - .irq = INT_44XX_DSP_MMU, - .pdata = { - .name = "tesla", - .nr_tlb_entries = 32, - .clk_name = "tesla_ick", - .da_start = 0x0, - .da_end = 0xFFFFF000, - }, + .name = "tesla", + .oh_name = "dsp", + .nr_tlb_entries = 32, + .da_start = 0x0, + .da_end = 0xFFFFF000, }, -#endif }; -#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices) -static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES]; +#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices_data) #else -#define omap4_devices NULL +#define omap4_devices_data NULL #define NR_OMAP4_IOMMU_DEVICES 0 -#define omap4_iommu_pdev NULL #endif -static struct platform_device **omap_iommu_pdev; +static struct omap_device_pm_latency omap_iommu_latency[] = { + [0] = { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int iommu_get_plat_data_size() +{ + return num_iommu_devices; +} +EXPORT_SYMBOL(iommu_get_plat_data_size); + +struct iommu_platform_data *iommu_get_device_data(void) +{ + return devices_data; +} static int __init omap_iommu_init(void) { - int i, err; - struct resource res[] = { - { .flags = IORESOURCE_MEM }, - { .flags = IORESOURCE_IRQ }, - }; + int i, ohl_cnt; + struct omap_hwmod *oh; + struct omap_device *od; + struct omap_device_pm_latency *ohl; if (cpu_is_omap34xx()) { - devices = omap3_devices; - omap_iommu_pdev = omap3_iommu_pdev; + devices_data = omap3_devices_data; num_iommu_devices = NR_OMAP3_IOMMU_DEVICES; } else if (cpu_is_omap44xx()) { - devices = omap4_devices; - omap_iommu_pdev = omap4_iommu_pdev; + devices_data = omap4_devices_data; num_iommu_devices = NR_OMAP4_IOMMU_DEVICES; } else return -ENODEV; + ohl = omap_iommu_latency; + ohl_cnt = ARRAY_SIZE(omap_iommu_latency); + for (i = 0; i < num_iommu_devices; i++) { - struct platform_device *pdev; - const struct iommu_device *d = &devices[i]; + struct iommu_platform_data *data = &devices_data[i]; - pdev = platform_device_alloc("omap-iommu", i); - if (!pdev) { - err = -ENOMEM; - goto err_out; - } + oh = omap_hwmod_lookup(data->oh_name); + data->io_base = oh->_mpu_rt_va; + data->irq = oh->mpu_irqs[0].irq; - res[0].start = d->base; - res[0].end = d->base + MMU_REG_SIZE - 1; - res[1].start = res[1].end = d->irq; - - err = platform_device_add_resources(pdev, res, - ARRAY_SIZE(res)); - if (err) - goto err_out; - err = platform_device_add_data(pdev, &d->pdata, - sizeof(d->pdata)); - if (err) - goto err_out; - err = platform_device_add(pdev); - if (err) - goto err_out; - omap_iommu_pdev[i] = pdev; + if (!oh) { + pr_err("%s: could not look up %s\n", __func__, + data->oh_name); + continue; + } + od = omap_device_build("omap-iommu", i, oh, + data, sizeof(*data), + ohl, ohl_cnt, false); + WARN(IS_ERR(od), "Could not build omap_device" + "for %s %s\n", "omap-iommu", data->oh_name); } return 0; - -err_out: - while (i--) - platform_device_put(omap_iommu_pdev[i]); - return err; } module_init(omap_iommu_init); -static void __exit omap_iommu_exit(void) -{ - int i; - - for (i = 0; i < num_iommu_devices; i++) - platform_device_unregister(omap_iommu_pdev[i]); -} -module_exit(omap_iommu_exit); - MODULE_AUTHOR("Hiroshi DOYU"); +MODULE_AUTHOR("Hari Kanigeri"); MODULE_DESCRIPTION("omap iommu: omap device registration"); MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index ecfe93c..8ad6957 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -26,11 +26,19 @@ #include <mach/hardware.h> #include <mach/omap4-common.h> +#include "clockdomain.h" + /* SCU base address */ static void __iomem *scu_base; static DEFINE_SPINLOCK(boot_lock); + +void __iomem *omap4_get_scu_base(void) +{ + return scu_base; +} + void __cpuinit platform_secondary_init(unsigned int cpu) { /* @@ -49,6 +57,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu) int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { + static struct clockdomain *cpu1_clkdm; + static bool booted; /* * Set synchronisation state between this boot processor * and the secondary one @@ -64,7 +74,27 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) omap_modify_auxcoreboot0(0x200, 0xfffffdff); flush_cache_all(); smp_wmb(); - gic_raise_softirq(cpumask_of(cpu), 1); + + if (!cpu1_clkdm) + cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); + + /* + * The SGI(Software Generated Interrupts) are not wakeup capable + * from low power states. This is known limitation on OMAP4 and + * needs to be worked around by using software forced clockdomain + * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to + * software force wakeup. After the wakeup, CPU1 restores its + * clockdomain hardware supervised mode. + * More details can be found in OMAP4430 TRM - Version J + * Section : + * 4.3.4.2 Power States of CPU0 and CPU1 + */ + if (booted) { + clkdm_wakeup(cpu1_clkdm); + } else { + dsb_sev(); + booted = true; + } /* * Now the secondary core is starting up let it run its diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c new file mode 100644 index 0000000..345a55c --- /dev/null +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -0,0 +1,319 @@ +/* + * OMAP WakeupGen Source file + * + * The WakeupGen unit is responsible for generating wakeup event from the + * incoming interrupts and enable bits. The WakeupGen is implemented in MPU + * always-On power domain. The WakeupGen consists of two sub-units, one for + * each CPU and manages only SPI interrupts. Hardware requirements is that + * the GIC and WakeupGen should be kept in sync for proper operation. + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Written by Santosh Shilimkar <santosh.shilimkar@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/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/platform_device.h> + +#include <asm/hardware/gic.h> + +#include <mach/omap-wakeupgen.h> +#include <mach/omap4-common.h> + +#include "omap4-sar-layout.h" + +#define NR_BANKS 4 +#define MAX_IRQS 128 +#define WKG_MASK_ALL 0x00000000 +#define WKG_UNMASK_ALL 0xffffffff +#define CPU_ENA_OFFSET 0x400 +#define CPU0_ID 0x0 +#define CPU1_ID 0x1 + +/* WakeupGen Base addres */ +static void __iomem *wakeupgen_base; +static void __iomem *sar_base; +static DEFINE_PER_CPU(u32 [NR_BANKS], irqmasks); +static DEFINE_SPINLOCK(wakeupgen_lock); + +/* + * Static helper functions + */ + +static inline u32 wakeupgen_readl(u8 idx, u32 cpu) +{ + return __raw_readl(wakeupgen_base + OMAP_WKG_ENB_A_0 + + (cpu * CPU_ENA_OFFSET) + (idx * 4)); +} + +static inline void wakeupgen_writel(u32 val, u8 idx, u32 cpu) +{ + __raw_writel(val, wakeupgen_base + OMAP_WKG_ENB_A_0 + + (cpu * CPU_ENA_OFFSET) + (idx * 4)); +} + +static inline void sar_writel(u32 val, u32 offset, u8 idx) +{ + __raw_writel(val, sar_base + offset + (idx * 4)); +} + +static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg) +{ + u8 i; + + for (i = 0; i < NR_BANKS; i++) + wakeupgen_writel(reg, i, cpu); +} + +static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index) +{ + unsigned int spi_irq; + + /* + * PPIs and SGIs are not supported + */ + if (irq < OMAP44XX_IRQ_GIC_START) + return -EINVAL; + + /* + * Subtract the GIC offset + */ + spi_irq = irq - OMAP44XX_IRQ_GIC_START; + if (spi_irq > MAX_IRQS) { + pr_err("omap wakeupGen: Invalid IRQ%d\n", irq); + return -EINVAL; + } + + /* + * Each wakeup gen register controls 32 + * interrupts. i.e 1 bit per SPI IRQ + */ + *reg_index = spi_irq >> 5; + *bit_posn = spi_irq %= 32; + + return 0; +} + +static void _wakeupgen_clear(unsigned int irq) +{ + unsigned int cpu = smp_processor_id(); + u32 val, bit_number; + u8 i; + + if (_wakeupgen_get_irq_info(irq, &bit_number, &i)) + return; + + val = wakeupgen_readl(i, cpu); + val &= ~BIT(bit_number); + wakeupgen_writel(val, i, cpu); +} + +static void _wakeupgen_set(unsigned int irq) +{ + unsigned int cpu = smp_processor_id(); + u32 val, bit_number; + u8 i; + + if (_wakeupgen_get_irq_info(irq, &bit_number, &i)) + return; + + val = wakeupgen_readl(i, cpu); + val |= BIT(bit_number); + wakeupgen_writel(val, i, cpu); +} + +static void _wakeupgen_save_masks(unsigned int cpu) +{ + u8 i; + + for (i = 0; i < NR_BANKS; i++) + per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu); +} + +static void _wakeupgen_restore_masks(unsigned int cpu) +{ + u8 i; + + for (i = 0; i < NR_BANKS; i++) + wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu); +} + +/* + * Architecture specific Mask extensiom + */ +static void wakeupgen_mask(struct irq_data *d) +{ + spin_lock(&wakeupgen_lock); + _wakeupgen_clear(d->irq); + spin_unlock(&wakeupgen_lock); +} + +/* + * Architecture specific Unmask extensiom + */ +static void wakeupgen_unmask(struct irq_data *d) +{ + + spin_lock(&wakeupgen_lock); + _wakeupgen_set(d->irq); + spin_unlock(&wakeupgen_lock); +} + +#ifdef CONFIG_PM +/* + * Architecture specific set_wake extension + */ +static int wakeupgen_set_wake(struct irq_data *d, unsigned int on) +{ + spin_lock(&wakeupgen_lock); + if (on) + _wakeupgen_set(d->irq); + else + _wakeupgen_clear(d->irq); + spin_unlock(&wakeupgen_lock); + + return 0; +} + +#else +#define wakeupgen_set_wake NULL +#endif + +/** + * omap_wakeupgen_irqmask_all() - Mask or unmask interrupts + * @cpu - CPU ID + * @set - The IRQ register mask. + * 0 = Mask all interrupts on the 'cpu' + * 1 = Unmask all interrupts on the 'cpu' + * + * Ensure that the initial mask is maintained. This is faster than + * iterating through GIC rgeisters to arrive at the correct masks + */ +void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set) +{ + if (omap_rev() == OMAP4430_REV_ES1_0) + return; + + spin_lock(&wakeupgen_lock); + if (set) { + _wakeupgen_save_masks(cpu); + _wakeupgen_set_all(cpu, WKG_MASK_ALL); + } else { + _wakeupgen_set_all(cpu, WKG_UNMASK_ALL); + _wakeupgen_restore_masks(cpu); + } + spin_unlock(&wakeupgen_lock); +} + +/* + * Initialse the wakeupgen module + */ +int __init omap_wakeupgen_init(void) +{ + u8 i; + + /* Not supported on on OMAP4 ES1.0 silicon */ + if (omap_rev() == OMAP4430_REV_ES1_0) { + WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n"); + return -EPERM; + } + + /* Static mapping, never released */ + wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K); + if (WARN_ON(!wakeupgen_base)) + return -ENODEV; + + /* Clear all IRQ bitmasks at wakeupGen level */ + for (i = 0; i < NR_BANKS; i++) { + wakeupgen_writel(0, i, CPU0_ID); + wakeupgen_writel(0, i, CPU1_ID); + } + + /* + * Override gic architecture specific fucntioms to add + * OMAP WakeupGen interrupt controller along with GIC + */ + gic_arch_extn.irq_mask = wakeupgen_mask; + gic_arch_extn.irq_unmask = wakeupgen_unmask; + gic_arch_extn.irq_set_wake = wakeupgen_set_wake; + + return 0; +} + +/** + * omap_wakeupgen_save() - WakeupGen context save function + * + * Save WakewupGen context in SAR BANK3. Restore is done by ROM code. + * WakeupGen IP is integrated along with GIC to manage the + * interrupt wakeups from CPU low power states. It's located in + * always ON power domain. It manages masking/unmasking of + * Shared peripheral interrupts(SPI).So the interrupt enable/disable + * control should be in sync and consistent at WakeupGen and GIC so + * that interrupts are not lost. Hence GIC and WakeupGen are saved + * and restored together. + + * During normal operation, WakeupGen delivers external interrupts + * directly to the GIC. When the CPU asserts StandbyWFI, indicating + * it wants to enter lowpower state, the Standby Controller checks + * with the WakeupGen unit using the idlereq/idleack handshake to make + * sure there is no incoming interrupts. + */ + +void omap_wakeupgen_save(void) +{ + u8 i; + u32 val; + + if (omap_rev() == OMAP4430_REV_ES1_0) + return; + + if (!sar_base) + sar_base = omap4_get_sar_ram_base(); + + for (i = 0; i < NR_BANKS; i++) { + /* Save the CPUx interrupt mask for IRQ 0 to 127 */ + val = wakeupgen_readl(i, 0); + sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i); + val = wakeupgen_readl(i, 1); + sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i); + + /* + * Disable the secure interrupts for CPUx. The restore + * code blindly restores secure and non-secure interrupt + * masks from SAR RAM. Secure interrupts are not suppose + * to be enabled from HLOS. So overwrite the SAR location + * so that the secure interrupt remains disabled. + */ + sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i); + sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i); + } + + /* Save AuxBoot* registers */ + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET); + + /* Save SyncReq generation logic */ + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET); + + /* Save SyncReq generation logic */ + val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK); + __raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN); + __raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET); + + /* Set the Backup Bit Mask status */ + val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); + val |= SAR_BACKUP_STATUS_WAKEUPGEN; + __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); +} diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c new file mode 100644 index 0000000..2523b11 --- /dev/null +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -0,0 +1,275 @@ +/* + * OMAP2PLUS cpufreq driver + * + * CPU frequency scaling for OMAP using OPP information + * + * 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-2011 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/kernel.h> +#include <linux/sched.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/opp.h> +#include <linux/cpu.h> + +#include <asm/system.h> +#include <asm/smp_plat.h> +#include <asm/cpu.h> + +#include <plat/clock.h> +#include <plat/omap-pm.h> +#include <plat/common.h> + +#include <mach/hardware.h> + +#include "dvfs.h" + +static struct cpufreq_frequency_table *freq_table; +static atomic_t freq_table_users = ATOMIC_INIT(0); +static struct clk *mpu_clk; +static char *mpu_clk_name; +static struct device *mpu_dev; + +static int omap_verify_speed(struct cpufreq_policy *policy) +{ + if (!freq_table) + return -EINVAL; + return cpufreq_frequency_table_verify(policy, freq_table); +} + +static unsigned int omap_getspeed(unsigned int cpu) +{ + unsigned long rate; + + if (cpu >= NR_CPUS) + return 0; + + rate = clk_get_rate(mpu_clk) / 1000; + return rate; +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int i; + int ret = 0; + struct cpufreq_freqs freqs; + + if (!freq_table) { + dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__, + policy->cpu); + return -EINVAL; + } + + ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, + relation, &i); + if (ret) { + dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n", + __func__, policy->cpu, target_freq, ret); + return ret; + } + freqs.new = freq_table[i].frequency; + if (!freqs.new) { + dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__, + policy->cpu, target_freq); + return -EINVAL; + } + + freqs.old = omap_getspeed(policy->cpu); + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new && policy->cur == freqs.new) + return ret; + + if (!is_smp()) { + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + goto set_freq; + } + + /* notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + +set_freq: +#ifdef CONFIG_CPU_FREQ_DEBUG + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); +#endif + + ret = omap_device_scale(mpu_dev, mpu_dev, freqs.new * 1000); + + /* + * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies + * won't get updated when UP machine cpufreq build with + * CONFIG_SMP enabled. Below code is added only to manage that + * scenario + */ + freqs.new = omap_getspeed(policy->cpu); + if (!is_smp()) { + loops_per_jiffy = + cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + goto skip_lpj; + } + +#ifdef CONFIG_SMP + /* + * Note that loops_per_jiffy is not updated on SMP systems in + * cpufreq driver. So, update the per-CPU loops_per_jiffy value + * on frequency transition. We need to update all dependent CPUs. + */ + for_each_cpu(i, policy->cpus) + per_cpu(cpu_data, i).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, + freqs.old, freqs.new); +#endif + + /* notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + +skip_lpj: + return ret; +} + +static inline void freq_table_free(void) +{ + if (atomic_dec_and_test(&freq_table_users)) + opp_free_cpufreq_table(mpu_dev, &freq_table); +} + +static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + + mpu_clk = clk_get(NULL, mpu_clk_name); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + if (policy->cpu >= NR_CPUS) { + result = -EINVAL; + goto fail_ck; + } + + policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); + + if (atomic_inc_return(&freq_table_users) == 1) + result = opp_init_cpufreq_table(mpu_dev, &freq_table); + + if (result) { + dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n", + __func__, policy->cpu, result); + goto fail_ck; + } + + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (result) + goto fail_table; + + cpufreq_frequency_table_get_attr(freq_table, policy->cpu); + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(policy->cpu); + + /* + * On OMAP SMP configuartion, both processors share the voltage + * and clock. So both CPUs needs to be scaled together and hence + * needs software co-ordination. Use cpufreq affected_cpus + * interface to handle this scenario. Additional is_smp() check + * is to keep SMP_ON_UP build working. + */ + if (is_smp()) { + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; + cpumask_setall(policy->cpus); + } + + /* FIXME: what's the actual transition time? */ + policy->cpuinfo.transition_latency = 300 * 1000; + + return 0; + +fail_table: + freq_table_free(); +fail_ck: + clk_put(mpu_clk); + return result; +} + +static int omap_cpu_exit(struct cpufreq_policy *policy) +{ + freq_table_free(); + clk_put(mpu_clk); + return 0; +} + +static struct freq_attr *omap_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver omap_driver = { + .flags = CPUFREQ_STICKY, + .verify = omap_verify_speed, + .target = omap_target, + .get = omap_getspeed, + .init = omap_cpu_init, + .exit = omap_cpu_exit, + .name = "omap2plus", + .attr = omap_cpufreq_attr, +}; + +static int __init omap_cpufreq_init(void) +{ + if (cpu_is_omap24xx()) + mpu_clk_name = "virt_prcm_set"; + else if (cpu_is_omap34xx()) + mpu_clk_name = "dpll1_ck"; + else if (cpu_is_omap443x()) + mpu_clk_name = "dpll_mpu_ck"; + else if (cpu_is_omap446x()) + mpu_clk_name = "virt_dpll_mpu_ck"; + + if (!mpu_clk_name) { + pr_err("%s: unsupported Silicon?\n", __func__); + return -EINVAL; + } + + mpu_dev = omap2_get_mpuss_device(); + if (!mpu_dev) { + pr_warning("%s: unable to get the mpu device\n", __func__); + return -EINVAL; + } + + return cpufreq_register_driver(&omap_driver); +} + +static void __exit omap_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&omap_driver); +} + +MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs"); +MODULE_LICENSE("GPL"); +late_initcall(omap_cpufreq_init); +module_exit(omap_cpufreq_exit); diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 9ef8c29..c3e65f6 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -18,34 +18,84 @@ #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> +#include <asm/cacheflush.h> #include <mach/hardware.h> #include <mach/omap4-common.h> +#include <mach/omap-wakeupgen.h> + +#include "omap4-sar-layout.h" +#include "clockdomain.h" #ifdef CONFIG_CACHE_L2X0 -void __iomem *l2cache_base; +#define L2X0_POR_OFFSET_VALUE 0x9 +static void __iomem *l2cache_base; #endif -void __iomem *gic_dist_base_addr; +static void __iomem *gic_dist_base_addr; +static void __iomem *gic_cpu_base; +static void __iomem *sar_ram_base; +static struct clockdomain *l4_secure_clkdm; +void __iomem *omap4_get_gic_dist_base(void) +{ + return gic_dist_base_addr; +} + +void __iomem *omap4_get_gic_cpu_base(void) +{ + return gic_cpu_base; +} void __init gic_init_irq(void) { - void __iomem *gic_cpu_base; /* Static mapping, never released */ gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); - BUG_ON(!gic_dist_base_addr); + if (WARN_ON(!gic_dist_base_addr)) + return; /* Static mapping, never released */ gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512); - BUG_ON(!gic_cpu_base); + if (WARN_ON(!gic_cpu_base)) + return; + + omap_wakeupgen_init(); gic_init(0, 29, gic_dist_base_addr, gic_cpu_base); } +/* + * FIXME: Remove this GIC APIs once common GIG library starts + * supporting it. + */ +void gic_cpu_enable(void) +{ + __raw_writel(0xf0, gic_cpu_base + GIC_CPU_PRIMASK); + __raw_writel(1, gic_cpu_base + GIC_CPU_CTRL); +} + +void gic_cpu_disable(void) +{ + __raw_writel(0, gic_cpu_base + GIC_CPU_CTRL); +} + +void gic_dist_enable(void) +{ + __raw_writel(0x1, gic_dist_base_addr + GIC_DIST_CTRL); +} +void gic_dist_disable(void) +{ + __raw_writel(0, gic_dist_base_addr + GIC_CPU_CTRL); +} + #ifdef CONFIG_CACHE_L2X0 +void __iomem *omap4_get_l2cache_base(void) +{ + return l2cache_base; +} + static void omap4_l2x0_disable(void) { /* Disable PL310 L2 Cache controller */ @@ -61,6 +111,8 @@ static void omap4_l2x0_set_debug(unsigned long val) static int __init omap_l2_cache_init(void) { u32 aux_ctrl = 0; + u32 por_ctrl = 0; + u32 lockdown = 0; /* * To avoid code running on other OMAPs in @@ -71,30 +123,70 @@ static int __init omap_l2_cache_init(void) /* Static mapping, never released */ l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K); - BUG_ON(!l2cache_base); + if (WARN_ON(!l2cache_base)) + return -ENODEV; /* * 16-way associativity, parity disabled * Way size - 32KB (es1.0) * Way size - 64KB (es2.0 +) */ - aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) | - (0x1 << 25) | - (0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) | - (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT)); + aux_ctrl = readl_relaxed(l2cache_base + L2X0_AUX_CTRL); if (omap_rev() == OMAP4430_REV_ES1_0) { aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT; - } else { - aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | - (1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | - (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | - (1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) | - (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT)); + goto skip_aux_por_api; + } + + /* + * Drop instruction prefetch hint since it degrades the + * the performance. + */ + aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | + (1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | + (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | + (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT)); + + omap_smc1(0x109, aux_ctrl); + + /* Setup POR Control register */ + por_ctrl = readl_relaxed(l2cache_base + L2X0_PREFETCH_CTRL); + + /* + * Double linefill is available only on OMAP4460 L2X0. + * Undocumented bit 25 is set for better performance. + */ + if (cpu_is_omap446x()) + por_ctrl |= ((1 << L2X0_PREFETCH_DATA_PREFETCH_SHIFT) | + (1 << L2X0_PREFETCH_DOUBLE_LINEFILL_SHIFT) | + (1 << 25)); + + if (cpu_is_omap446x() || (omap_rev() >= OMAP4430_REV_ES2_2)) { + por_ctrl |= L2X0_POR_OFFSET_VALUE; + omap_smc1(0x113, por_ctrl); + } + + if (cpu_is_omap446x()) { + writel_relaxed(0xa5a5, l2cache_base + 0x900); + writel_relaxed(0xa5a5, l2cache_base + 0x908); + writel_relaxed(0xa5a5, l2cache_base + 0x904); + writel_relaxed(0xa5a5, l2cache_base + 0x90C); + } + + /* + * FIXME: Temporary WA for OMAP4460 stability issue. + * Lock-down specific L2 cache ways which makes effective + * L2 size as 512 KB instead of 1 MB + */ + if (cpu_is_omap446x()) { + lockdown = 0xa5a5; + writel_relaxed(lockdown, l2cache_base + L2X0_LOCKDOWN_WAY_D0); + writel_relaxed(lockdown, l2cache_base + L2X0_LOCKDOWN_WAY_D1); + writel_relaxed(lockdown, l2cache_base + L2X0_LOCKDOWN_WAY_I0); + writel_relaxed(lockdown, l2cache_base + L2X0_LOCKDOWN_WAY_I1); } - if (omap_rev() != OMAP4430_REV_ES1_0) - omap_smc1(0x109, aux_ctrl); +skip_aux_por_api: /* Enable PL310 L2 Cache controller */ omap_smc1(0x102, 0x1); @@ -111,3 +203,80 @@ static int __init omap_l2_cache_init(void) } early_initcall(omap_l2_cache_init); #endif + +void __iomem *omap4_get_sar_ram_base(void) +{ + return sar_ram_base; +} + +/* + * SAR RAM used to save and restore the HW + * context in low power modes + */ +static int __init omap4_sar_ram_init(void) +{ + /* + * To avoid code running on other OMAPs in + * multi-omap builds + */ + if (!cpu_is_omap44xx()) + return -ENODEV; + + /* Static mapping, never released */ + sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_8K); + if (WARN_ON(!sar_ram_base)) + return -ENODEV; + + l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm"); + + return 0; +} +early_initcall(omap4_sar_ram_init); + + +/* + * omap4_sec_dispatcher: Routine to dispatch low power secure + * service routines + * + * @idx: The HAL API index + * @flag: The flag indicating criticality of operation + * @nargs: Number of valid arguments out of four. + * @arg1, arg2, arg3 args4: Parameters passed to secure API + * + * Return the error value on success/failure + */ +u32 omap4_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2, + u32 arg3, u32 arg4) +{ + u32 ret; + u32 param[5]; + + param[0] = nargs; + param[1] = arg1; + param[2] = arg2; + param[3] = arg3; + param[4] = arg4; + + /* + * Put l4 secure to software wakeup so that secure + * modules are accessible + */ + clkdm_wakeup(l4_secure_clkdm); + + /* + * Secure API needs physical address + * pointer for the parameters + */ + flush_cache_all(); + outer_clean_range(__pa(param), __pa(param + 5)); + + ret = omap_smc2(idx, flag, __pa(param)); + + /* + * Restore l4 secure to hardware superwised to allow + * secure modules idle + */ + clkdm_allow_idle(l4_secure_clkdm); + + return ret; +} diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c new file mode 100644 index 0000000..bf98bf2 --- /dev/null +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c @@ -0,0 +1,526 @@ +/* + * OMAP4 MPUSS low power code + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Written by Santosh Shilimkar <santosh.shilimkar@ti.com> + * + * OMAP4430 MPUSS mainly consists of dual Cortex-A9 with per-CPU + * Local timer and Watchdog, GIC, SCU, PL310 L2 cache controller, + * CPU0 and CPU1 LPRM modules. + * CPU0, CPU1 and MPUSS each have there own power domain and + * hence multiple low power combinations of MPUSS are possible. + * + * The CPU0 and CPU1 can't support Closed switch Retention (CSWR) + * because the mode is not supported by hw constraints of dormant + * mode. While waking up from the dormant mode, a reset signal + * to the Cortex-A9 processor must be asserted by the external + * power controller. + * + * With architectural inputs and hardware recommendations, only + * below modes are supported from power gain vs latency point of view. + * + * CPU0 CPU1 MPUSS + * ---------------------------------------------- + * ON ON ON + * ON(Inactive) OFF ON(Inactive) + * OFF OFF CSWR + * OFF OFF OSWR (*TBD) + * OFF OFF OFF + * ---------------------------------------------- + * + * Note: CPU0 is the master core and it is the last CPU to go down + * and first to wake-up when MPUSS low power states are excercised + * + * + * 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/io.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <linux/dma-mapping.h> + +#include <asm/tlbflush.h> +#include <asm/smp_scu.h> +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/hardware/gic.h> +#include <asm/hardware/cache-l2x0.h> + +#include <plat/omap44xx.h> +#include <mach/omap4-common.h> +#include <mach/omap-wakeupgen.h> + +#include "omap4-sar-layout.h" +#include "pm.h" +#include "powerdomain.h" + +#ifdef CONFIG_SMP + +#define GIC_MASK_ALL 0x0 +#define GIC_ISR_NON_SECURE 0xffffffff +#define SPI_ENABLE_SET_OFFSET 0x04 +#define PPI_PRI_OFFSET 0x1c +#define SPI_PRI_OFFSET 0x20 +#define SPI_TARGET_OFFSET 0x20 +#define SPI_CONFIG_OFFSET 0x20 + +/* GIC save SAR bank base */ +static struct powerdomain *mpuss_pd; +/* + * Maximum Secure memory storage size. + */ +#define OMAP4_SECURE_RAM_STORAGE (88 * SZ_1K) +/* + * Physical address of secure memory storage + */ +dma_addr_t omap4_secure_ram_phys; +static void *secure_ram; + +/* Variables to store maximum spi(Shared Peripheral Interrupts) registers. */ +static u32 max_spi_irq, max_spi_reg; + +struct omap4_cpu_pm_info { + struct powerdomain *pwrdm; + void __iomem *scu_sar_addr; + void __iomem *l1_sar_addr; +}; + +static void __iomem *gic_dist_base; +static void __iomem *sar_base; + +static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); + +/* Helper functions */ +static inline void sar_writel(u32 val, u32 offset, u8 idx) +{ + __raw_writel(val, sar_base + offset + 4 * idx); +} + +static inline u32 gic_readl(u32 offset, u8 idx) +{ + return __raw_readl(gic_dist_base + offset + 4 * idx); +} + +/* + * Set the CPUx powerdomain's previous power state + */ +static inline void set_cpu_next_pwrst(unsigned int cpu_id, + unsigned int power_state) +{ + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + + pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); +} + +/* + * Read CPU's previous power state + */ +static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id) +{ + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + + return pwrdm_read_prev_pwrst(pm_info->pwrdm); +} + +/* + * Clear the CPUx powerdomain's previous power state + */ +static inline void clear_cpu_prev_pwrst(unsigned int cpu_id) +{ + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); +} + +/* + * Store the SCU power status value to scratchpad memory + */ +static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state) +{ + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + u32 scu_pwr_st, l1_state; + + switch (cpu_state) { + case PWRDM_POWER_RET: + scu_pwr_st = SCU_PM_DORMANT; + l1_state = 0x00; + break; + case PWRDM_POWER_OFF: + scu_pwr_st = SCU_PM_POWEROFF; + l1_state = 0xff; + break; + case PWRDM_POWER_ON: + case PWRDM_POWER_INACTIVE: + default: + scu_pwr_st = SCU_PM_NORMAL; + l1_state = 0x00; + break; + } + + __raw_writel(scu_pwr_st, pm_info->scu_sar_addr); + __raw_writel(scu_pwr_st, pm_info->l1_sar_addr); +} + +/* + * Save GIC context in SAR RAM. Restore is done by ROM code + * GIC is lost only when MPU hits OSWR or OFF. It consists + * of a distributor and a per-CPU interface module. The GIC + * save restore is optimised to save only necessary registers. + */ +static void gic_save_context(void) +{ + u8 i; + u32 val; + + /* + * Interrupt Clear Enable registers are inverse of set enable + * and hence not needed to be saved. ROM code programs it + * based on Set Enable register values. + */ + + /* Save CPU 0 Interrupt Set Enable register */ + val = gic_readl(GIC_DIST_ENABLE_SET, 0); + sar_writel(val, ICDISER_CPU0_OFFSET, 0); + + /* Disable interrupts on CPU1 */ + sar_writel(GIC_MASK_ALL, ICDISER_CPU1_OFFSET, 0); + + /* Save all SPI Set Enable register */ + for (i = 0; i < max_spi_reg; i++) { + val = gic_readl(GIC_DIST_ENABLE_SET + SPI_ENABLE_SET_OFFSET, i); + sar_writel(val, ICDISER_SPI_OFFSET, i); + } + + /* + * Interrupt Priority Registers + * Secure sw accesses, last 5 bits of the 8 bits (bit[7:3] are used) + * Non-Secure sw accesses, last 4 bits (i.e. bits[7:4] are used) + * But the Secure Bits[7:3] are shifted by 1 in Non-Secure access. + * Secure (bits[7:3] << 1)== Non Secure bits[7:4] + * Hence right shift the value by 1 while saving the priority + */ + + /* Save SGI priority registers (Software Generated Interrupt) */ + for (i = 0; i < 4; i++) { + val = gic_readl(GIC_DIST_PRI, i); + + /* Save the priority bits of the Interrupts */ + sar_writel(val >> 0x1, ICDIPR_SFI_CPU0_OFFSET, i); + + /* Disable the interrupts on CPU1 */ + sar_writel(GIC_MASK_ALL, ICDIPR_SFI_CPU1_OFFSET, i); + } + + /* Save PPI priority registers (Private Peripheral Intterupts) */ + val = gic_readl(GIC_DIST_PRI + PPI_PRI_OFFSET, 0); + sar_writel(val >> 0x1, ICDIPR_PPI_CPU0_OFFSET, 0); + sar_writel(GIC_MASK_ALL, ICDIPR_PPI_CPU1_OFFSET, 0); + + /* SPI priority registers - 4 interrupts/register */ + for (i = 0; i < (max_spi_irq / 4); i++) { + val = gic_readl((GIC_DIST_PRI + SPI_PRI_OFFSET), i); + sar_writel(val >> 0x1, ICDIPR_SPI_OFFSET, i); + } + + /* SPI Interrupt Target registers - 4 interrupts/register */ + for (i = 0; i < (max_spi_irq / 4); i++) { + val = gic_readl((GIC_DIST_TARGET + SPI_TARGET_OFFSET), i); + sar_writel(val, ICDIPTR_SPI_OFFSET, i); + } + + /* SPI Interrupt Congigeration eegisters- 16 interrupts/register */ + for (i = 0; i < (max_spi_irq / 16); i++) { + val = gic_readl((GIC_DIST_CONFIG + SPI_CONFIG_OFFSET), i); + sar_writel(val, ICDICFR_OFFSET, i); + } + + /* Set the Backup Bit Mask status for GIC */ + val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); + val |= (SAR_BACKUP_STATUS_GIC_CPU0 | SAR_BACKUP_STATUS_GIC_CPU1); + __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); +} +/* + * API to save GIC and Wakeupgen using secure API + * for HS/EMU device + */ +static void save_gic_wakeupgen_secure(void) +{ + u32 ret; + ret = omap4_secure_dispatcher(HAL_SAVEGIC_INDEX, + FLAG_IRQFIQ_MASK | FLAG_START_CRITICAL, + 0, 0, 0, 0, 0); + if (!ret) + pr_debug("GIC and Wakeupgen context save failed\n"); +} + +/* + * API to save Secure RAM using secure API + * for HS/EMU device + */ +static void save_secure_ram(void) +{ + u32 ret; + ret = omap4_secure_dispatcher(HAL_SAVESECURERAM_INDEX, + FLAG_IRQFIQ_MASK | FLAG_START_CRITICAL, + 1, omap4_secure_ram_phys, 0, 0, 0); + if (!ret) + pr_debug("Secure ram context save failed\n"); +} + +/* + * OMAP4 MPUSS Low Power Entry Function + * + * The purpose of this function is to manage low power programming + * of OMAP4 MPUSS subsystem + * Paramenters: + * cpu : CPU ID + * power_state: Targetted Low power state. + * + * MPUSS Low power states + * The basic rule is that the MPUSS power domain must be at the higher or + * equal power state (state that consume more power) than the higher of the + * two CPUs. For example, it is illegal for system power to be OFF, while + * the power of one or both of the CPU is DORMANT. When an illegal state is + * entered, then the hardware behavior is unpredictable. + * + * MPUSS state for the context save + * save_state = + * 0 - Nothing lost and no need to save: MPUSS INACTIVE + * 1 - CPUx L1 and logic lost: MPUSS CSWR + * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR + * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF + */ +int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) +{ + unsigned int save_state = 0; + unsigned int wakeup_cpu; + + if ((cpu >= NR_CPUS) || (omap_rev() == OMAP4430_REV_ES1_0)) + goto ret; + + switch (power_state) { + case PWRDM_POWER_ON: + case PWRDM_POWER_INACTIVE: + save_state = 0; + break; + case PWRDM_POWER_OFF: + save_state = 1; + break; + case PWRDM_POWER_RET: + default: + /* + * CPUx CSWR is invalid hardware state. Also CPUx OSWR + * doesn't make much scense, since logic is lost and $L1 + * needs to be cleaned because of coherency. This makes + * CPUx OSWR equivalent to CPUX OFF and hence not supported + */ + WARN_ON(1); + goto ret; + } + + /* + * MPUSS book keeping should be executed by master + * CPU only which is also the last CPU to go down. + */ + if (cpu) + goto cpu_prepare; + + pwrdm_pre_transition(); + + /* + * Check MPUSS next state and save GIC if needed + * GIC lost during MPU OFF and OSWR + */ + pwrdm_clear_all_prev_pwrst(mpuss_pd); + if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) { + if (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF) { + if (omap_type() != OMAP2_DEVICE_TYPE_GP) { + save_gic_wakeupgen_secure(); + } else { + omap_wakeupgen_save(); + gic_save_context(); + } + } + } + if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) { + if (omap_type() != OMAP2_DEVICE_TYPE_GP) { + save_secure_ram(); + save_gic_wakeupgen_secure(); + } else { + omap_wakeupgen_save(); + gic_save_context(); + } + save_state = 3; + } + +cpu_prepare: + clear_cpu_prev_pwrst(cpu); + set_cpu_next_pwrst(cpu, power_state); + scu_pwrst_prepare(cpu, power_state); + + /* + * Call low level function with targeted CPU id + * and its low power state. + */ + omap4_cpu_suspend(cpu, save_state); + + /* + * Restore the CPUx power state to ON otherwise CPUx + * power domain can transitions to programmed low power + * state while doing WFI outside the low powe code. On + * secure devices, CPUx does WFI which can result in + * domain transition + */ + wakeup_cpu = hard_smp_processor_id(); + set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); + + /* If !master cpu return to hotplug-path */ + if (wakeup_cpu) + goto ret; + + /* Check MPUSS previous power state and enable GIC if needed */ + if (pwrdm_read_prev_pwrst(mpuss_pd) == PWRDM_POWER_OFF) { + /* Clear SAR BACKUP status */ + __raw_writel(0x0, sar_base + SAR_BACKUP_STATUS_OFFSET); + /* Enable GIC distributor and inteface on CPU0*/ + gic_cpu_enable(); + gic_dist_enable(); + } + + pwrdm_post_transition(); + +ret: + return 0; +} + +static void save_l2x0_auxctrl(void) +{ +#ifdef CONFIG_CACHE_L2X0 + /* + * Save the L2X0 AUXCTRL value to SAR memory. Its used to + * in every restore patch MPUSS OFF path. + */ + void __iomem *l2x0_base = omap4_get_l2cache_base(); + u32 val; + + val = __raw_readl(l2x0_base + L2X0_AUX_CTRL); + __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET); +#endif +} + +/* + * Initialise OMAP4 MPUSS + */ +int __init omap4_mpuss_init(void) +{ + struct omap4_cpu_pm_info *pm_info; + u8 i; + + /* Get GIC and SAR RAM base addresses */ + sar_base = omap4_get_sar_ram_base(); + gic_dist_base = omap4_get_gic_dist_base(); + + if (omap_rev() == OMAP4430_REV_ES1_0) { + WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); + return -ENODEV; + } + + /* Initilaise per CPU PM information */ + pm_info = &per_cpu(omap4_pm_info, 0x0); + pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; + pm_info->l1_sar_addr = sar_base + L1_OFFSET0; + pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); + if (!pm_info->pwrdm) { + pr_err("Lookup failed for CPU0 pwrdm\n"); + return -ENODEV; + } + + /* Clear CPU previous power domain state */ + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); + + /* Initialise CPU0 power domain state to ON */ + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); + + pm_info = &per_cpu(omap4_pm_info, 0x1); + pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; + pm_info->l1_sar_addr = sar_base + L1_OFFSET1; + pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); + if (!pm_info->pwrdm) { + pr_err("Lookup failed for CPU1 pwrdm\n"); + return -ENODEV; + } + + /* + * Check the OMAP type and store it to scratchpad + */ + if (omap_type() != OMAP2_DEVICE_TYPE_GP) { + /* Memory not released */ + secure_ram = dma_alloc_coherent(NULL, OMAP4_SECURE_RAM_STORAGE, + (dma_addr_t *)&omap4_secure_ram_phys, GFP_ATOMIC); + if (!secure_ram) + pr_err("Unable to allocate secure ram storage\n"); + writel(0x1, sar_base + OMAP_TYPE_OFFSET); + } else { + writel(0x0, sar_base + OMAP_TYPE_OFFSET); + } + + /* Clear CPU previous power domain state */ + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); + + /* Initialise CPU1 power domain state to ON */ + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); + + /* + * Program the wakeup routine address for the CPU0 and CPU1 + * used for OFF or DORMANT wakeup. Wakeup routine address + * is fixed so programit in init itself. + */ + __raw_writel(virt_to_phys(omap4_cpu_resume), + sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET); + __raw_writel(virt_to_phys(omap4_cpu_resume), + sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET); + + mpuss_pd = pwrdm_lookup("mpu_pwrdm"); + if (!mpuss_pd) { + pr_err("Failed to get lookup for MPUSS pwrdm\n"); + return -ENODEV; + } + + /* Clear CPU previous power domain state */ + pwrdm_clear_all_prev_pwrst(mpuss_pd); + + /* + * Find out how many interrupts are supported. + * OMAP4 supports max of 128 SPIs where as GIC can support + * up to 1020 interrupt sources. On OMAP4, maximum SPIs are + * fused in DIST_CTR bit-fields as 128. Hence the code is safe + * from reserved register writes since its well within 1020. + */ + max_spi_reg = __raw_readl(gic_dist_base + GIC_DIST_CTR) & 0x1f; + max_spi_irq = max_spi_reg * 32; + + /* + * Mark the PPI and SPI interrupts as non-secure. + * program the SAR locations for interrupt security registers to + * reflect the same. + */ + if (omap_type() == OMAP2_DEVICE_TYPE_GP) { + sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0); + sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0); + for (i = 0; i < max_spi_reg; i++) + sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i); + } + save_l2x0_auxctrl(); + + return 0; +} + +#endif + diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h new file mode 100644 index 0000000..0ded2cf --- /dev/null +++ b/arch/arm/mach-omap2/omap4-sar-layout.h @@ -0,0 +1,70 @@ +/* + * omap4-sar-layout.h: OMAP4 SAR RAM layout header file + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Santosh Shilimkar <santosh.shilimkar@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. + */ +#ifndef OMAP_ARCH_OMAP4_SAR_LAYOUT_H +#define OMAP_ARCH_OMAP4_SAR_LAYOUT_H + +/* + * SAR BANK offsets from base address OMAP44XX_SAR_RAM_BASE + */ +#define SAR_BANK1_OFFSET 0x0000 +#define SAR_BANK2_OFFSET 0x1000 +#define SAR_BANK3_OFFSET 0x2000 +#define SAR_BANK4_OFFSET 0x3000 + +/* Scratch pad memory offsets from SAR_BANK1 */ +#define CPU0_SAVE_OFFSET 0xb00 +#define CPU1_SAVE_OFFSET 0xc00 +#define MMU_OFFSET0 0xd00 +#define MMU_OFFSET1 0xd10 +#define SCU_OFFSET0 0xd20 +#define SCU_OFFSET1 0xd24 +#define L2X0_OFFSET 0xd28 +#define L2X0_AUXCTRL_OFFSET 0xd2c +#define L1_OFFSET0 0xd30 +#define L1_OFFSET1 0xd34 +#define OMAP_TYPE_OFFSET 0xd38 + +/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */ +#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04 +#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08 + +/* GIC save restore offset from SAR_BANK3 */ +#define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500) +#define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504) +#define SAR_SECRAM_SAVED_AT_OFFSET (SAR_BANK3_OFFSET + 0x508) +#define ICDISR_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x50c) +#define ICDISR_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x510) +#define ICDISR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x514) +#define ICDISER_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x524) +#define ICDISER_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x528) +#define ICDISER_SPI_OFFSET (SAR_BANK3_OFFSET + 0x52c) +#define ICDIPR_SFI_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x53c) +#define ICDIPR_PPI_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x54c) +#define ICDIPR_SFI_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x550) +#define ICDIPR_PPI_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x560) +#define ICDIPR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x564) +#define ICDIPTR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x5e4) +#define ICDICFR_OFFSET (SAR_BANK3_OFFSET + 0x664) +#define SAR_BACKUP_STATUS_GIC_CPU0 0x1 +#define SAR_BACKUP_STATUS_GIC_CPU1 0x2 + +/* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */ +#define WAKEUPGENENB_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x684) +#define WAKEUPGENENB_SECURE_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x694) +#define WAKEUPGENENB_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6a4) +#define WAKEUPGENENB_SECURE_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6b4) +#define AUXCOREBOOT0_OFFSET (SAR_BANK3_OFFSET + 0x6c4) +#define AUXCOREBOOT1_OFFSET (SAR_BANK3_OFFSET + 0x6c8) +#define PTMSYNCREQ_MASK_OFFSET (SAR_BANK3_OFFSET + 0x6cc) +#define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0) +#define SAR_BACKUP_STATUS_WAKEUPGEN 0x10 + +#endif diff --git a/arch/arm/mach-omap2/omap44xx-smc.S b/arch/arm/mach-omap2/omap44xx-smc.S index e69d37d..83ba6d9 100644 --- a/arch/arm/mach-omap2/omap44xx-smc.S +++ b/arch/arm/mach-omap2/omap44xx-smc.S @@ -31,6 +31,30 @@ ENTRY(omap_smc1) ldmfd sp!, {r2-r12, pc} ENDPROC(omap_smc1) +/* + * Low level common routine to manage secure + * HAL APIs. + * Function signature : u32 omap_smc2(u32 id, u32 falg, u32 pargs) + * @id : Application ID of HAL APIs + * @flag : Flag to indicate the criticality of operation + * @pargs : Physical address of parameter list starting + * with number of parametrs + */ +ENTRY(omap_smc2) + stmfd sp!, {r1-r12, lr} + mov r3, r2 + mov r2, r1 + mov r1, #0x0 @ Process ID + mov r6, #0xff + mov r12, #0x00 @ Secure Service ID + mov r7, #0 + mcr p15, 0, r7, c7, c5, 6 + dsb + dmb + smc #0 + ldmfd sp!, {r1-r12, pc} +END(omap_smc2) + ENTRY(omap_modify_auxcoreboot0) stmfd sp!, {r1-r12, lr} ldr r12, =0x104 diff --git a/arch/arm/mach-omap2/omap4_trim_quirks.c b/arch/arm/mach-omap2/omap4_trim_quirks.c new file mode 100644 index 0000000..0ee5bb0 --- /dev/null +++ b/arch/arm/mach-omap2/omap4_trim_quirks.c @@ -0,0 +1,78 @@ +/* + * OMAP LDO control and configuration + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/cpu.h> + +#include "control.h" + +/** + * omap4_ldo_trim_configure() - Handle device trim variance + * + * Few of the silicon out of the fab come out without trim parameters + * efused in. These need some software support to allow the device to + * function normally. Handle these silicon quirks here. + */ +static int __init omap4_ldo_trim_configure(void) +{ + u32 is_trimmed = 0; + u32 val; + + /* Applicable only for OMAP4 */ + if (!cpu_is_omap44xx()) + return 0; + + /* + * Some ES2.2 efuse values for BGAP and SLDO trim + * are not programmed. For these units + * 1. we can set overide mode for SLDO trim, + * and program the max multiplication factor, to ensure + * high enough voltage on SLDO output. + * 2. trim VDAC value for TV output as per recomendation + */ + + if (omap_rev() == CHIP_IS_OMAP4430ES2_2) + is_trimmed = omap_ctrl_readl( + OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL); + + /* if not trimmed, we set force overide, insted of efuse. */ + if (!is_trimmed) { + /* Fill in recommended values */ + val = 0x0f << OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT; + val |= OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK; + val |= 0x1 << OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT; + val |= OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK; + + omap_ctrl_writel(val, + OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL); + omap_ctrl_writel(val, + OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL); + omap_ctrl_writel(val, + OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL); + + /* write value as per trim recomendation */ + val = 0xc0 << OMAP4_AVDAC_TRIM_BYTE0_SHIFT; + val |= 0x01 << OMAP4_AVDAC_TRIM_BYTE1_SHIFT; + omap_ctrl_writel(val, + OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1); + } + + /* + * For all ESx.y trimmed and untrimmed units LPDDR IO and + * Smart IO override efuse. + */ + val = OMAP4_LPDDR2_PTV_P5_MASK | OMAP4_LPDDR2_PTV_N5_MASK; + omap_ctrl_writel(val, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2); + + return 0; +} +arch_initcall(omap4_ldo_trim_configure); diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 4f0d554..94573ef 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -401,7 +401,8 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v) wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); - *v |= wakeup_mask; + if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) + *v |= wakeup_mask; if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v); @@ -436,7 +437,8 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); - *v &= ~wakeup_mask; + if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) + *v &= ~wakeup_mask; if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v); @@ -1223,6 +1225,7 @@ static int _reset(struct omap_hwmod *oh) static int _enable(struct omap_hwmod *oh) { int r; + int hwsup = 0; if (oh->_state != _HWMOD_STATE_INITIALIZED && oh->_state != _HWMOD_STATE_IDLE && @@ -1250,10 +1253,16 @@ static int _enable(struct omap_hwmod *oh) omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); _add_initiator_dep(oh, mpu_oh); + if (oh->_clk && oh->_clk->clkdm) { + hwsup = clkdm_is_idle(oh->_clk->clkdm); + clkdm_wakeup(oh->_clk->clkdm); + } _enable_clocks(oh); - r = _wait_target_ready(oh); if (!r) { + if (oh->_clk && oh->_clk->clkdm && hwsup) + clkdm_allow_idle(oh->_clk->clkdm); + oh->_state = _HWMOD_STATE_ENABLED; /* Access the sysconfig only if the target is ready */ @@ -1374,8 +1383,11 @@ static int _shutdown(struct omap_hwmod *oh) } } - if (oh->class->sysc) + if (oh->class->sysc) { + if (oh->_state == _HWMOD_STATE_IDLE) + _enable(oh); _shutdown_sysc(oh); + } /* * If an IP contains only one HW reset line, then assert it @@ -1628,7 +1640,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), void *data) { struct omap_hwmod *temp_oh; - int ret; + int ret = 0; if (!fn) return -EINVAL; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 5fac4c0..3dad446 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -29,6 +29,7 @@ #include "omap_hwmod_common_data.h" +#include "smartreflex.h" #include "prm-regbits-34xx.h" #include "cm-regbits-34xx.h" #include "wd_timer.h" @@ -2943,6 +2944,10 @@ static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = { }; /* SR1 */ +static struct omap_smartreflex_dev_attr sr1_dev_attr = { + .sensor_voltdm_name = "mpu_iva", +}; + static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = { &omap3_l4_core__sr1, }; @@ -2951,7 +2956,6 @@ static struct omap_hwmod omap34xx_sr1_hwmod = { .name = "sr1_hwmod", .class = &omap34xx_smartreflex_hwmod_class, .main_clk = "sr1_fck", - .vdd_name = "mpu", .prcm = { .omap2 = { .prcm_reg_id = 1, @@ -2963,6 +2967,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = { }, .slaves = omap3_sr1_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves), + .dev_attr = &sr1_dev_attr, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), @@ -2973,7 +2978,6 @@ static struct omap_hwmod omap36xx_sr1_hwmod = { .name = "sr1_hwmod", .class = &omap36xx_smartreflex_hwmod_class, .main_clk = "sr1_fck", - .vdd_name = "mpu", .prcm = { .omap2 = { .prcm_reg_id = 1, @@ -2985,10 +2989,15 @@ static struct omap_hwmod omap36xx_sr1_hwmod = { }, .slaves = omap3_sr1_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves), + .dev_attr = &sr1_dev_attr, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), }; /* SR2 */ +static struct omap_smartreflex_dev_attr sr2_dev_attr = { + .sensor_voltdm_name = "core", +}; + static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = { &omap3_l4_core__sr2, }; @@ -2997,7 +3006,6 @@ static struct omap_hwmod omap34xx_sr2_hwmod = { .name = "sr2_hwmod", .class = &omap34xx_smartreflex_hwmod_class, .main_clk = "sr2_fck", - .vdd_name = "core", .prcm = { .omap2 = { .prcm_reg_id = 1, @@ -3009,6 +3017,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = { }, .slaves = omap3_sr2_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves), + .dev_attr = &sr2_dev_attr, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), @@ -3019,7 +3028,6 @@ static struct omap_hwmod omap36xx_sr2_hwmod = { .name = "sr2_hwmod", .class = &omap36xx_smartreflex_hwmod_class, .main_clk = "sr2_fck", - .vdd_name = "core", .prcm = { .omap2 = { .prcm_reg_id = 1, @@ -3031,6 +3039,7 @@ static struct omap_hwmod omap36xx_sr2_hwmod = { }, .slaves = omap3_sr2_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves), + .dev_attr = &sr2_dev_attr, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), }; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 15a6e8b..22a45f8 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -30,6 +30,7 @@ #include "omap_hwmod_common_data.h" +#include "smartreflex.h" #include "cm1_44xx.h" #include "cm2_44xx.h" #include "prm44xx.h" @@ -49,6 +50,8 @@ static struct omap_hwmod omap44xx_dmm_hwmod; static struct omap_hwmod omap44xx_dsp_hwmod; static struct omap_hwmod omap44xx_dss_hwmod; static struct omap_hwmod omap44xx_emif_fw_hwmod; +static struct omap_hwmod omap44xx_fdif_hwmod; +static struct omap_hwmod omap44xx_gpu_hwmod; static struct omap_hwmod omap44xx_hsi_hwmod; static struct omap_hwmod omap44xx_ipu_hwmod; static struct omap_hwmod omap44xx_iss_hwmod; @@ -65,6 +68,7 @@ static struct omap_hwmod omap44xx_mmc1_hwmod; static struct omap_hwmod omap44xx_mmc2_hwmod; static struct omap_hwmod omap44xx_mpu_hwmod; static struct omap_hwmod omap44xx_mpu_private_hwmod; +static struct omap_hwmod omap44xx_sl2if_hwmod; static struct omap_hwmod omap44xx_usb_otg_hs_hwmod; /* @@ -124,7 +128,7 @@ static struct omap_hwmod omap44xx_dmm_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_dmm_slaves), .mpu_irqs = omap44xx_dmm_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dmm_irqs), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -173,7 +177,7 @@ static struct omap_hwmod omap44xx_emif_fw_hwmod = { .class = &omap44xx_emif_fw_hwmod_class, .slaves = omap44xx_emif_fw_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_emif_fw_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -212,7 +216,7 @@ static struct omap_hwmod omap44xx_l3_instr_hwmod = { .class = &omap44xx_l3_hwmod_class, .slaves = omap44xx_l3_instr_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l3_instr_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* l3_main_1 interface data */ @@ -306,7 +310,7 @@ static struct omap_hwmod omap44xx_l3_main_1_hwmod = { .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_l3_targ_irqs), .slaves = omap44xx_l3_main_1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* l3_main_2 interface data */ @@ -318,6 +322,14 @@ static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* gpu -> l3_main_2 */ +static struct omap_hwmod_ocp_if omap44xx_gpu__l3_main_2 = { + .master = &omap44xx_gpu_hwmod, + .slave = &omap44xx_l3_main_2_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* hsi -> l3_main_2 */ static struct omap_hwmod_ocp_if omap44xx_hsi__l3_main_2 = { .master = &omap44xx_hsi_hwmod, @@ -342,6 +354,14 @@ static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* fdif -> l3_main_2 */ +static struct omap_hwmod_ocp_if omap44xx_fdif__l3_main_2 = { + .master = &omap44xx_fdif_hwmod, + .slave = &omap44xx_l3_main_2_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* iva -> l3_main_2 */ static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = { .master = &omap44xx_iva_hwmod, @@ -390,8 +410,10 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = { &omap44xx_hsi__l3_main_2, &omap44xx_ipu__l3_main_2, &omap44xx_iss__l3_main_2, + &omap44xx_fdif__l3_main_2, &omap44xx_iva__l3_main_2, &omap44xx_l3_main_1__l3_main_2, + &omap44xx_gpu__l3_main_2, &omap44xx_l4_cfg__l3_main_2, &omap44xx_usb_otg_hs__l3_main_2, }; @@ -401,7 +423,7 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = { .class = &omap44xx_l3_hwmod_class, .slaves = omap44xx_l3_main_2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* l3_main_3 interface data */ @@ -451,7 +473,7 @@ static struct omap_hwmod omap44xx_l3_main_3_hwmod = { .class = &omap44xx_l3_hwmod_class, .slaves = omap44xx_l3_main_3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -508,7 +530,7 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = { .class = &omap44xx_l4_hwmod_class, .slaves = omap44xx_l4_abe_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l4_abe_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* l4_cfg interface data */ @@ -530,7 +552,7 @@ static struct omap_hwmod omap44xx_l4_cfg_hwmod = { .class = &omap44xx_l4_hwmod_class, .slaves = omap44xx_l4_cfg_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l4_cfg_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* l4_per interface data */ @@ -552,7 +574,7 @@ static struct omap_hwmod omap44xx_l4_per_hwmod = { .class = &omap44xx_l4_hwmod_class, .slaves = omap44xx_l4_per_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l4_per_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* l4_wkup interface data */ @@ -574,7 +596,7 @@ static struct omap_hwmod omap44xx_l4_wkup_hwmod = { .class = &omap44xx_l4_hwmod_class, .slaves = omap44xx_l4_wkup_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_l4_wkup_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -604,7 +626,7 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { .class = &omap44xx_mpu_bus_hwmod_class, .slaves = omap44xx_mpu_private_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mpu_private_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -629,7 +651,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { * elm * emif1 * emif2 - * fdif * gpmc * gpu * hdq1w @@ -640,7 +661,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { * prcm_mpu * prm * scrm - * sl2if * slimbus1 * slimbus2 * usb_host_fs @@ -651,6 +671,222 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { */ /* + * 'mpu' class + * mpu sub-system + */ + +static struct omap_hwmod_class omap44xx_mpu_hwmod_class = { + .name = "mpu", +}; + +/* mpu */ +static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = { + { .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START }, + { .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START }, + { .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START }, +}; + +/* mpu master ports */ +static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = { + &omap44xx_mpu__l3_main_1, + &omap44xx_mpu__l4_abe, + &omap44xx_mpu__dmm, +}; + +static struct omap_hwmod omap44xx_mpu_hwmod = { + .name = "mpu", + .class = &omap44xx_mpu_hwmod_class, + .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), + .mpu_irqs = omap44xx_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mpu_irqs), + .main_clk = "dpll_mpu_m2_ck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL, + }, + }, + .masters = omap44xx_mpu_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_mpu_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* + * 'smartreflex' class + * smartreflex module (monitor silicon performance and outputs a measure of + * performance error) + */ + +/* The IP is not compliant to type1 / type2 scheme */ +static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_smartreflex = { + .sidle_shift = 24, + .enwkup_shift = 26, +}; + +static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = { + .sysc_offs = 0x0038, + .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + SIDLE_SMART_WKUP), + .sysc_fields = &omap_hwmod_sysc_type_smartreflex, +}; + +static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = { + .name = "smartreflex", + .sysc = &omap44xx_smartreflex_sysc, + .rev = 2, +}; + +/* smartreflex_core */ +static struct omap_smartreflex_dev_attr smartreflex_core_dev_attr = { + .sensor_voltdm_name = "core", +}; + +static struct omap_hwmod omap44xx_smartreflex_core_hwmod; +static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = { + { .irq = 19 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = { + { + .pa_start = 0x4a0dd000, + .pa_end = 0x4a0dd03f, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> smartreflex_core */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_smartreflex_core_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_smartreflex_core_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* smartreflex_core slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = { + &omap44xx_l4_cfg__smartreflex_core, +}; + +static struct omap_hwmod omap44xx_smartreflex_core_hwmod = { + .name = "smartreflex_core", + .class = &omap44xx_smartreflex_hwmod_class, + .mpu_irqs = omap44xx_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_irqs), + .main_clk = "smartreflex_core_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL, + }, + }, + .slaves = omap44xx_smartreflex_core_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_slaves), + .dev_attr = &smartreflex_core_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* smartreflex_iva */ +static struct omap_smartreflex_dev_attr smartreflex_iva_dev_attr = { + .sensor_voltdm_name = "iva", +}; + +static struct omap_hwmod omap44xx_smartreflex_iva_hwmod; +static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = { + { .irq = 102 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = { + { + .pa_start = 0x4a0db000, + .pa_end = 0x4a0db03f, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> smartreflex_iva */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_smartreflex_iva_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_smartreflex_iva_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* smartreflex_iva slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = { + &omap44xx_l4_cfg__smartreflex_iva, +}; + +static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = { + .name = "smartreflex_iva", + .class = &omap44xx_smartreflex_hwmod_class, + .mpu_irqs = omap44xx_smartreflex_iva_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_irqs), + .main_clk = "smartreflex_iva_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL, + }, + }, + .slaves = omap44xx_smartreflex_iva_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_slaves), + .dev_attr = &smartreflex_iva_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* smartreflex_mpu */ +static struct omap_smartreflex_dev_attr smartreflex_mpu_dev_attr = { + .sensor_voltdm_name = "mpu", +}; + +static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod; +static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = { + { .irq = 18 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = { + { + .pa_start = 0x4a0d9000, + .pa_end = 0x4a0d903f, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> smartreflex_mpu */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_smartreflex_mpu_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_smartreflex_mpu_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* smartreflex_mpu slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = { + &omap44xx_l4_cfg__smartreflex_mpu, +}; + +static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = { + .name = "smartreflex_mpu", + .class = &omap44xx_smartreflex_hwmod_class, + .mpu_irqs = omap44xx_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs), + .main_clk = "smartreflex_mpu_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL, + }, + }, + .slaves = omap44xx_smartreflex_mpu_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves), + .dev_attr = &smartreflex_mpu_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* * 'aess' class * audio engine sub system */ @@ -658,7 +894,7 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { static struct omap_hwmod_class_sysconfig omap44xx_aess_sysc = { .rev_offs = 0x0000, .sysc_offs = 0x0010, - .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), + .sysc_flags = 0, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), .sysc_fields = &omap_hwmod_sysc_type2, @@ -692,6 +928,27 @@ static struct omap_hwmod_ocp_if *omap44xx_aess_masters[] = { static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = { { + .name = "dmem", + .pa_start = 0x40180000, + .pa_end = 0x4018ffff + }, + { + .name = "cmem", + .pa_start = 0x401a0000, + .pa_end = 0x401a1fff + }, + { + .name = "smem", + .pa_start = 0x401c0000, + .pa_end = 0x401c5fff + }, + { + .name = "pmem", + .pa_start = 0x401e0000, + .pa_end = 0x401e1fff + }, + { + .name = "mpu", .pa_start = 0x401f1000, .pa_end = 0x401f13ff, .flags = ADDR_TYPE_RT @@ -710,6 +967,27 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = { static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = { { + .name = "dmem_dma", + .pa_start = 0x49080000, + .pa_end = 0x4908ffff + }, + { + .name = "cmem_dma", + .pa_start = 0x490a0000, + .pa_end = 0x490a1fff + }, + { + .name = "smem_dma", + .pa_start = 0x490c0000, + .pa_end = 0x490c5fff + }, + { + .name = "pmem_dma", + .pa_start = 0x490e0000, + .pa_end = 0x490e1fff + }, + { + .name = "dma", .pa_start = 0x490f1000, .pa_end = 0x490f13ff, .flags = ADDR_TYPE_RT @@ -749,7 +1027,7 @@ static struct omap_hwmod omap44xx_aess_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_aess_slaves), .masters = omap44xx_aess_masters, .masters_cnt = ARRAY_SIZE(omap44xx_aess_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -762,11 +1040,11 @@ static struct omap_hwmod_class omap44xx_bandgap_hwmod_class = { }; /* bandgap */ -static struct omap_hwmod_opt_clk bandgap_opt_clks[] = { +static struct omap_hwmod_opt_clk bandgap443x_opt_clks[] = { { .role = "fclk", .clk = "bandgap_fclk" }, }; -static struct omap_hwmod omap44xx_bandgap_hwmod = { +static struct omap_hwmod omap443x_bandgap_hwmod = { .name = "bandgap", .class = &omap44xx_bandgap_hwmod_class, .prcm = { @@ -774,9 +1052,26 @@ static struct omap_hwmod omap44xx_bandgap_hwmod = { .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, }, }, - .opt_clks = bandgap_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(bandgap_opt_clks), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .opt_clks = bandgap443x_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(bandgap443x_opt_clks), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP443X), +}; + +static struct omap_hwmod_opt_clk bandgap446x_opt_clks[] = { + { .role = "fclk", .clk = "bandgap_ts_fclk" }, +}; + +static struct omap_hwmod omap446x_bandgap_hwmod = { + .name = "bandgap", + .class = &omap44xx_bandgap_hwmod_class, + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, + }, + }, + .opt_clks = bandgap446x_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(bandgap446x_opt_clks), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), }; /* @@ -835,7 +1130,7 @@ static struct omap_hwmod omap44xx_counter_32k_hwmod = { }, .slaves = omap44xx_counter_32k_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_counter_32k_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -921,7 +1216,7 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_dma_system_slaves), .masters = omap44xx_dma_system_masters, .masters_cnt = ARRAY_SIZE(omap44xx_dma_system_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1011,7 +1306,7 @@ static struct omap_hwmod omap44xx_dmic_hwmod = { }, .slaves = omap44xx_dmic_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dmic_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1036,6 +1331,14 @@ static struct omap_hwmod_rst_info omap44xx_dsp_c0_resets[] = { { .name = "dsp", .rst_shift = 0 }, }; +static struct omap_hwmod_addr_space omap44xx_dsp_addrs[] = { + { + .pa_start = 0x4A066000, + .pa_end = 0x4A0660ff, + .flags = ADDR_TYPE_RT + }, +}; + /* dsp -> iva */ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { .master = &omap44xx_dsp_hwmod, @@ -1043,11 +1346,19 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { .clk = "dpll_iva_m5x2_ck", }; +/* dsp -> sl2if */ +static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = { + .master = &omap44xx_dsp_hwmod, + .slave = &omap44xx_sl2if_hwmod, + .clk = "dpll_iva_m5x2_ck", +}; + /* dsp master ports */ static struct omap_hwmod_ocp_if *omap44xx_dsp_masters[] = { &omap44xx_dsp__l3_main_1, &omap44xx_dsp__l4_abe, &omap44xx_dsp__iva, + &omap44xx_dsp__sl2if, }; /* l4_cfg -> dsp */ @@ -1055,6 +1366,8 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dsp = { .master = &omap44xx_l4_cfg_hwmod, .slave = &omap44xx_dsp_hwmod, .clk = "l4_div_ck", + .addr = omap44xx_dsp_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dsp_addrs), .user = OCP_USER_MPU | OCP_USER_SDMA, }; @@ -1075,12 +1388,13 @@ static struct omap_hwmod omap44xx_dsp_c0_hwmod = { .rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL, }, }, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct omap_hwmod omap44xx_dsp_hwmod = { .name = "dsp", .class = &omap44xx_dsp_hwmod_class, + .flags = HWMOD_INIT_NO_RESET, .mpu_irqs = omap44xx_dsp_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dsp_irqs), .rst_lines = omap44xx_dsp_resets, @@ -1096,7 +1410,7 @@ static struct omap_hwmod omap44xx_dsp_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_dsp_slaves), .masters = omap44xx_dsp_masters, .masters_cnt = ARRAY_SIZE(omap44xx_dsp_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1240,7 +1554,7 @@ static struct omap_hwmod omap44xx_dss_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_dss_slaves), .masters = omap44xx_dss_masters, .masters_cnt = ARRAY_SIZE(omap44xx_dss_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1347,7 +1661,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = { .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks), .slaves = omap44xx_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1445,7 +1759,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = { .opt_clks_cnt = ARRAY_SIZE(dsi1_opt_clks), .slaves = omap44xx_dss_dsi1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* dss_dsi2 */ @@ -1515,7 +1829,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = { }, .slaves = omap44xx_dss_dsi2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1612,7 +1926,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { .opt_clks_cnt = ARRAY_SIZE(hdmi_opt_clks), .slaves = omap44xx_dss_hdmi_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1702,7 +2016,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = { .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks), .slaves = omap44xx_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1775,7 +2089,78 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = { .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks), .slaves = omap44xx_dss_venc_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_venc_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* + * 'fdif' class + * face detection hw accelerator module + */ + +static struct omap_hwmod_class_sysconfig omap44xx_fdif_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class omap44xx_fdif_hwmod_class = { + .name = "fdif", + .sysc = &omap44xx_fdif_sysc, +}; + +/* fdif */ +static struct omap_hwmod_irq_info omap44xx_fdif_irqs[] = { + { .irq = 69 + OMAP44XX_IRQ_GIC_START }, +}; + +/* fdif master ports */ +static struct omap_hwmod_ocp_if *omap44xx_fdif_masters[] = { + &omap44xx_fdif__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_fdif_addrs[] = { + { + .pa_start = 0x4a10a000, + .pa_end = 0x4a10a1ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> fdif */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__fdif = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_fdif_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_fdif_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_fdif_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* fdif slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_fdif_slaves[] = { + &omap44xx_l3_main_2__fdif, +}; + +static struct omap_hwmod omap44xx_fdif_hwmod = { + .name = "fdif", + .class = &omap44xx_fdif_hwmod_class, + .mpu_irqs = omap44xx_fdif_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_fdif_irqs), + .main_clk = "fdif_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL, + }, + }, + .slaves = omap44xx_fdif_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_fdif_slaves), + .masters = omap44xx_fdif_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_fdif_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -1840,9 +2225,29 @@ static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { { .role = "dbclk", .clk = "gpio1_dbclk" }, }; -static struct omap_hwmod omap44xx_gpio1_hwmod = { +static struct omap_hwmod omap443x_gpio1_hwmod = { + .name = "gpio1", + .class = &omap44xx_gpio_hwmod_class, + .mpu_irqs = omap44xx_gpio1_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio1_irqs), + .main_clk = "gpio1_ick", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL, + }, + }, + .opt_clks = gpio1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .dev_attr = &gpio_dev_attr, + .slaves = omap44xx_gpio1_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_gpio1_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP443X), +}; + +static struct omap_hwmod omap446x_gpio1_hwmod = { .name = "gpio1", .class = &omap44xx_gpio_hwmod_class, + .flags = HWMOD_INIT_NO_RESET, .mpu_irqs = omap44xx_gpio1_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio1_irqs), .main_clk = "gpio1_ick", @@ -1856,7 +2261,7 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = { .dev_attr = &gpio_dev_attr, .slaves = omap44xx_gpio1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_gpio1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), }; /* gpio2 */ @@ -1895,7 +2300,8 @@ static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { static struct omap_hwmod omap44xx_gpio2_hwmod = { .name = "gpio2", .class = &omap44xx_gpio_hwmod_class, - .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET | + HWMOD_SWSUP_SIDLE , .mpu_irqs = omap44xx_gpio2_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpio2_irqs), .main_clk = "gpio2_ick", @@ -1909,7 +2315,7 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = { .dev_attr = &gpio_dev_attr, .slaves = omap44xx_gpio2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_gpio2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* gpio3 */ @@ -1962,7 +2368,7 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = { .dev_attr = &gpio_dev_attr, .slaves = omap44xx_gpio3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_gpio3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* gpio4 */ @@ -2015,7 +2421,7 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = { .dev_attr = &gpio_dev_attr, .slaves = omap44xx_gpio4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_gpio4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* gpio5 */ @@ -2068,7 +2474,7 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = { .dev_attr = &gpio_dev_attr, .slaves = omap44xx_gpio5_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_gpio5_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* gpio6 */ @@ -2121,7 +2527,44 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = { .dev_attr = &gpio_dev_attr, .slaves = omap44xx_gpio6_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_gpio6_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* + * 'gpu' class + * 2d/3d graphics accelerator + */ + +static struct omap_hwmod_class_sysconfig omap44xx_gpu_sysc = { + .rev_offs = 0xfe00, + .sysc_offs = 0xfe10, + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class omap44xx_gpu_hwmod_class = { + .name = "gpu", + .sysc = &omap44xx_gpu_sysc, +}; + +/* gpu */ +static struct omap_hwmod_irq_info omap44xx_gpu_irqs[] = { + { .irq = 21 + OMAP44XX_IRQ_GIC_START }, +}; + +/* gpu master ports */ +static struct omap_hwmod_ocp_if *omap44xx_gpu_masters[] = { + &omap44xx_gpu__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_gpu_addrs[] = { + { + .pa_start = 0x56000000, + .pa_end = 0x5600ffff, + .flags = ADDR_TYPE_RT + }, }; /* @@ -2198,7 +2641,41 @@ static struct omap_hwmod omap44xx_hsi_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_hsi_slaves), .masters = omap44xx_hsi_masters, .masters_cnt = ARRAY_SIZE(omap44xx_hsi_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* l3_main_2 -> gpu */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpu = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_gpu_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_gpu_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_gpu_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* gpu slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_gpu_slaves[] = { + &omap44xx_l3_main_2__gpu, +}; + +static struct omap_hwmod omap44xx_gpu_hwmod = { + .name = "gpu", + .class = &omap44xx_gpu_hwmod_class, + .mpu_irqs = omap44xx_gpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_gpu_irqs), + .main_clk = "gpu_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_GFX_GFX_CLKCTRL, + }, + }, + .slaves = omap44xx_gpu_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_gpu_slaves), + .masters = omap44xx_gpu_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_gpu_masters), + .dev_attr = &smartreflex_core_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2272,7 +2749,7 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = { }, .slaves = omap44xx_i2c1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_i2c1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* i2c2 */ @@ -2325,7 +2802,7 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = { }, .slaves = omap44xx_i2c2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_i2c2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* i2c3 */ @@ -2378,7 +2855,7 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = { }, .slaves = omap44xx_i2c3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_i2c3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* i2c4 */ @@ -2431,7 +2908,7 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = { }, .slaves = omap44xx_i2c4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_i2c4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2460,6 +2937,14 @@ static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = { { .name = "mmu_cache", .rst_shift = 2 }, }; +static struct omap_hwmod_addr_space omap44xx_ipu_addrs[] = { + { + .pa_start = 0x55082000, + .pa_end = 0x550820ff, + .flags = ADDR_TYPE_RT + }, +}; + /* ipu master ports */ static struct omap_hwmod_ocp_if *omap44xx_ipu_masters[] = { &omap44xx_ipu__l3_main_2, @@ -2470,6 +2955,8 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_ipu_hwmod, .clk = "l3_div_ck", + .addr = omap44xx_ipu_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_ipu_addrs), .user = OCP_USER_MPU | OCP_USER_SDMA, }; @@ -2490,7 +2977,7 @@ static struct omap_hwmod omap44xx_ipu_c0_hwmod = { .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL, }, }, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* Pseudo hwmod for reset control purpose only */ @@ -2505,12 +2992,13 @@ static struct omap_hwmod omap44xx_ipu_c1_hwmod = { .rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL, }, }, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct omap_hwmod omap44xx_ipu_hwmod = { .name = "ipu", .class = &omap44xx_ipu_hwmod_class, + .flags = HWMOD_INIT_NO_RESET, .mpu_irqs = omap44xx_ipu_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_ipu_irqs), .rst_lines = omap44xx_ipu_resets, @@ -2526,7 +3014,7 @@ static struct omap_hwmod omap44xx_ipu_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_ipu_slaves), .masters = omap44xx_ipu_masters, .masters_cnt = ARRAY_SIZE(omap44xx_ipu_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2613,7 +3101,7 @@ static struct omap_hwmod omap44xx_iss_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_iss_slaves), .masters = omap44xx_iss_masters, .masters_cnt = ARRAY_SIZE(omap44xx_iss_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2644,8 +3132,16 @@ static struct omap_hwmod_rst_info omap44xx_iva_seq1_resets[] = { { .name = "seq1", .rst_shift = 1 }, }; +/* iva -> sl2if */ +static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = { + .master = &omap44xx_iva_hwmod, + .slave = &omap44xx_sl2if_hwmod, + .clk = "dpll_iva_m5x2_ck", +}; + /* iva master ports */ static struct omap_hwmod_ocp_if *omap44xx_iva_masters[] = { + &omap44xx_iva__sl2if, &omap44xx_iva__l3_main_2, &omap44xx_iva__l3_instr, }; @@ -2686,7 +3182,7 @@ static struct omap_hwmod omap44xx_iva_seq0_hwmod = { .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL, }, }, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* Pseudo hwmod for reset control purpose only */ @@ -2701,7 +3197,7 @@ static struct omap_hwmod omap44xx_iva_seq1_hwmod = { .rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL, }, }, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static struct omap_hwmod omap44xx_iva_hwmod = { @@ -2722,7 +3218,46 @@ static struct omap_hwmod omap44xx_iva_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_iva_slaves), .masters = omap44xx_iva_masters, .masters_cnt = ARRAY_SIZE(omap44xx_iva_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* + * 'sl2if' class + * shared level 2 memory interface + */ + +static struct omap_hwmod_class omap44xx_sl2if_hwmod_class = { + .name = "sl2if", +}; + +/* sl2if */ +/* l3_main_2 -> sl2if */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_sl2if_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* sl2if slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_sl2if_slaves[] = { + &omap44xx_l3_main_2__sl2if, + &omap44xx_iva__sl2if, + &omap44xx_dsp__sl2if, +}; + +static struct omap_hwmod omap44xx_sl2if_hwmod = { + .name = "sl2if", + .class = &omap44xx_sl2if_hwmod_class, + .main_clk = "sl2if_ick", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_IVAHD_SL2_CLKCTRL, + }, + }, + .slaves = omap44xx_sl2if_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_sl2if_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2789,7 +3324,7 @@ static struct omap_hwmod omap44xx_kbd_hwmod = { }, .slaves = omap44xx_kbd_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_kbd_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2853,7 +3388,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = { }, .slaves = omap44xx_mailbox_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mailbox_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -2878,7 +3413,8 @@ static struct omap_hwmod_class omap44xx_mcbsp_hwmod_class = { /* mcbsp1 */ static struct omap_hwmod omap44xx_mcbsp1_hwmod; static struct omap_hwmod_irq_info omap44xx_mcbsp1_irqs[] = { - { .irq = 17 + OMAP44XX_IRQ_GIC_START }, + { .name = "tx", .irq = 17 + OMAP44XX_IRQ_GIC_START }, + { .name = "rx", .irq = 0 }, }; static struct omap_hwmod_dma_info omap44xx_mcbsp1_sdma_reqs[] = { @@ -2945,13 +3481,14 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = { }, .slaves = omap44xx_mcbsp1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mcbsp2 */ static struct omap_hwmod omap44xx_mcbsp2_hwmod; static struct omap_hwmod_irq_info omap44xx_mcbsp2_irqs[] = { - { .irq = 22 + OMAP44XX_IRQ_GIC_START }, + { .name = "tx", .irq = 22 + OMAP44XX_IRQ_GIC_START }, + { .name = "rx", .irq = 0 }, }; static struct omap_hwmod_dma_info omap44xx_mcbsp2_sdma_reqs[] = { @@ -3018,13 +3555,14 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = { }, .slaves = omap44xx_mcbsp2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mcbsp3 */ static struct omap_hwmod omap44xx_mcbsp3_hwmod; static struct omap_hwmod_irq_info omap44xx_mcbsp3_irqs[] = { - { .irq = 23 + OMAP44XX_IRQ_GIC_START }, + { .name = "tx", .irq = 23 + OMAP44XX_IRQ_GIC_START }, + { .name = "rx", .irq = 0 }, }; static struct omap_hwmod_dma_info omap44xx_mcbsp3_sdma_reqs[] = { @@ -3091,13 +3629,14 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = { }, .slaves = omap44xx_mcbsp3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mcbsp4 */ static struct omap_hwmod omap44xx_mcbsp4_hwmod; static struct omap_hwmod_irq_info omap44xx_mcbsp4_irqs[] = { - { .irq = 16 + OMAP44XX_IRQ_GIC_START }, + { .name = "tx", .irq = 16 + OMAP44XX_IRQ_GIC_START }, + { .name = "rx", .irq = 0 }, }; static struct omap_hwmod_dma_info omap44xx_mcbsp4_sdma_reqs[] = { @@ -3143,7 +3682,7 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = { }, .slaves = omap44xx_mcbsp4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -3235,7 +3774,7 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = { }, .slaves = omap44xx_mcpdm_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcpdm_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -3321,7 +3860,7 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = { .dev_attr = &mcspi1_dev_attr, .slaves = omap44xx_mcspi1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mcspi2 */ @@ -3381,7 +3920,7 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = { .dev_attr = &mcspi2_dev_attr, .slaves = omap44xx_mcspi2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mcspi3 */ @@ -3441,7 +3980,7 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = { .dev_attr = &mcspi3_dev_attr, .slaves = omap44xx_mcspi3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mcspi4 */ @@ -3499,7 +4038,7 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = { .dev_attr = &mcspi4_dev_attr, .slaves = omap44xx_mcspi4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -3586,7 +4125,7 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_mmc1_slaves), .masters = omap44xx_mmc1_masters, .masters_cnt = ARRAY_SIZE(omap44xx_mmc1_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mmc2 */ @@ -3644,7 +4183,7 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_mmc2_slaves), .masters = omap44xx_mmc2_masters, .masters_cnt = ARRAY_SIZE(omap44xx_mmc2_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mmc3 */ @@ -3696,7 +4235,7 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = { }, .slaves = omap44xx_mmc3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mmc3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mmc4 */ @@ -3748,7 +4287,7 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = { }, .slaves = omap44xx_mmc4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mmc4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* mmc5 */ @@ -3800,211 +4339,7 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = { }, .slaves = omap44xx_mmc5_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mmc5_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), -}; - -/* - * 'mpu' class - * mpu sub-system - */ - -static struct omap_hwmod_class omap44xx_mpu_hwmod_class = { - .name = "mpu", -}; - -/* mpu */ -static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = { - { .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START }, - { .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START }, - { .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START }, -}; - -/* mpu master ports */ -static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = { - &omap44xx_mpu__l3_main_1, - &omap44xx_mpu__l4_abe, - &omap44xx_mpu__dmm, -}; - -static struct omap_hwmod omap44xx_mpu_hwmod = { - .name = "mpu", - .class = &omap44xx_mpu_hwmod_class, - .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), - .mpu_irqs = omap44xx_mpu_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mpu_irqs), - .main_clk = "dpll_mpu_m2_ck", - .prcm = { - .omap4 = { - .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL, - }, - }, - .masters = omap44xx_mpu_masters, - .masters_cnt = ARRAY_SIZE(omap44xx_mpu_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), -}; - -/* - * 'smartreflex' class - * smartreflex module (monitor silicon performance and outputs a measure of - * performance error) - */ - -/* The IP is not compliant to type1 / type2 scheme */ -static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_smartreflex = { - .sidle_shift = 24, - .enwkup_shift = 26, -}; - -static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = { - .sysc_offs = 0x0038, - .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - SIDLE_SMART_WKUP), - .sysc_fields = &omap_hwmod_sysc_type_smartreflex, -}; - -static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = { - .name = "smartreflex", - .sysc = &omap44xx_smartreflex_sysc, - .rev = 2, -}; - -/* smartreflex_core */ -static struct omap_hwmod omap44xx_smartreflex_core_hwmod; -static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = { - { .irq = 19 + OMAP44XX_IRQ_GIC_START }, -}; - -static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = { - { - .pa_start = 0x4a0dd000, - .pa_end = 0x4a0dd03f, - .flags = ADDR_TYPE_RT - }, -}; - -/* l4_cfg -> smartreflex_core */ -static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = { - .master = &omap44xx_l4_cfg_hwmod, - .slave = &omap44xx_smartreflex_core_hwmod, - .clk = "l4_div_ck", - .addr = omap44xx_smartreflex_core_addrs, - .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_addrs), - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* smartreflex_core slave ports */ -static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = { - &omap44xx_l4_cfg__smartreflex_core, -}; - -static struct omap_hwmod omap44xx_smartreflex_core_hwmod = { - .name = "smartreflex_core", - .class = &omap44xx_smartreflex_hwmod_class, - .mpu_irqs = omap44xx_smartreflex_core_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_irqs), - .main_clk = "smartreflex_core_fck", - .vdd_name = "core", - .prcm = { - .omap4 = { - .clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL, - }, - }, - .slaves = omap44xx_smartreflex_core_slaves, - .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), -}; - -/* smartreflex_iva */ -static struct omap_hwmod omap44xx_smartreflex_iva_hwmod; -static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = { - { .irq = 102 + OMAP44XX_IRQ_GIC_START }, -}; - -static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = { - { - .pa_start = 0x4a0db000, - .pa_end = 0x4a0db03f, - .flags = ADDR_TYPE_RT - }, -}; - -/* l4_cfg -> smartreflex_iva */ -static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = { - .master = &omap44xx_l4_cfg_hwmod, - .slave = &omap44xx_smartreflex_iva_hwmod, - .clk = "l4_div_ck", - .addr = omap44xx_smartreflex_iva_addrs, - .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_addrs), - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* smartreflex_iva slave ports */ -static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = { - &omap44xx_l4_cfg__smartreflex_iva, -}; - -static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = { - .name = "smartreflex_iva", - .class = &omap44xx_smartreflex_hwmod_class, - .mpu_irqs = omap44xx_smartreflex_iva_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_irqs), - .main_clk = "smartreflex_iva_fck", - .vdd_name = "iva", - .prcm = { - .omap4 = { - .clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL, - }, - }, - .slaves = omap44xx_smartreflex_iva_slaves, - .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), -}; - -/* smartreflex_mpu */ -static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod; -static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = { - { .irq = 18 + OMAP44XX_IRQ_GIC_START }, -}; - -static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = { - { - .pa_start = 0x4a0d9000, - .pa_end = 0x4a0d903f, - .flags = ADDR_TYPE_RT - }, -}; - -/* l4_cfg -> smartreflex_mpu */ -static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = { - .master = &omap44xx_l4_cfg_hwmod, - .slave = &omap44xx_smartreflex_mpu_hwmod, - .clk = "l4_div_ck", - .addr = omap44xx_smartreflex_mpu_addrs, - .addr_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs), - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* smartreflex_mpu slave ports */ -static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = { - &omap44xx_l4_cfg__smartreflex_mpu, -}; - -static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = { - .name = "smartreflex_mpu", - .class = &omap44xx_smartreflex_hwmod_class, - .mpu_irqs = omap44xx_smartreflex_mpu_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs), - .main_clk = "smartreflex_mpu_fck", - .vdd_name = "mpu", - .prcm = { - .omap4 = { - .clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL, - }, - }, - .slaves = omap44xx_smartreflex_mpu_slaves, - .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -4065,7 +4400,7 @@ static struct omap_hwmod omap44xx_spinlock_hwmod = { }, .slaves = omap44xx_spinlock_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_spinlock_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -4148,7 +4483,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = { }, .slaves = omap44xx_timer1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer2 */ @@ -4193,7 +4528,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = { }, .slaves = omap44xx_timer2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer3 */ @@ -4238,7 +4573,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = { }, .slaves = omap44xx_timer3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer4 */ @@ -4283,7 +4618,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = { }, .slaves = omap44xx_timer4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer5 */ @@ -4347,7 +4682,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = { }, .slaves = omap44xx_timer5_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer5_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer6 */ @@ -4411,7 +4746,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = { }, .slaves = omap44xx_timer6_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer6_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer7 */ @@ -4475,7 +4810,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = { }, .slaves = omap44xx_timer7_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer7_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer8 */ @@ -4539,7 +4874,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = { }, .slaves = omap44xx_timer8_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer8_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer9 */ @@ -4584,7 +4919,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = { }, .slaves = omap44xx_timer9_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer9_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer10 */ @@ -4629,7 +4964,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = { }, .slaves = omap44xx_timer10_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer10_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* timer11 */ @@ -4674,7 +5009,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = { }, .slaves = omap44xx_timer11_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_timer11_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -4748,7 +5083,7 @@ static struct omap_hwmod omap44xx_uart1_hwmod = { }, .slaves = omap44xx_uart1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_uart1_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* uart2 */ @@ -4800,7 +5135,7 @@ static struct omap_hwmod omap44xx_uart2_hwmod = { }, .slaves = omap44xx_uart2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_uart2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* uart3 */ @@ -4853,7 +5188,7 @@ static struct omap_hwmod omap44xx_uart3_hwmod = { }, .slaves = omap44xx_uart3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_uart3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* uart4 */ @@ -4905,7 +5240,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = { }, .slaves = omap44xx_uart4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_uart4_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -4987,7 +5322,7 @@ static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_slaves), .masters = omap44xx_usb_otg_hs_masters, .masters_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_masters), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* @@ -5055,7 +5390,7 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = { }, .slaves = omap44xx_wd_timer2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer2_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; /* wd_timer3 */ @@ -5119,7 +5454,7 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { }, .slaves = omap44xx_wd_timer3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer3_slaves), - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; static __initdata struct omap_hwmod *omap44xx_hwmods[] = { @@ -5146,10 +5481,11 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_mpu_private_hwmod, /* aess class */ -/* &omap44xx_aess_hwmod, */ + &omap44xx_aess_hwmod, /* bandgap class */ - &omap44xx_bandgap_hwmod, + &omap443x_bandgap_hwmod, + &omap446x_bandgap_hwmod, /* counter class */ /* &omap44xx_counter_32k_hwmod, */ @@ -5174,7 +5510,8 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_dss_venc_hwmod, /* gpio class */ - &omap44xx_gpio1_hwmod, + &omap443x_gpio1_hwmod, + &omap446x_gpio1_hwmod, &omap44xx_gpio2_hwmod, &omap44xx_gpio3_hwmod, &omap44xx_gpio4_hwmod, @@ -5184,6 +5521,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* hsi class */ /* &omap44xx_hsi_hwmod, */ + /* gpu class */ + &omap44xx_gpu_hwmod, + /* i2c class */ &omap44xx_i2c1_hwmod, &omap44xx_i2c2_hwmod, @@ -5196,15 +5536,21 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_ipu_c1_hwmod, /* iss class */ -/* &omap44xx_iss_hwmod, */ + &omap44xx_iss_hwmod, + + /* fdif class */ + &omap44xx_fdif_hwmod, /* iva class */ &omap44xx_iva_hwmod, &omap44xx_iva_seq0_hwmod, &omap44xx_iva_seq1_hwmod, + /* sl2if class */ + &omap44xx_sl2if_hwmod, + /* kbd class */ -/* &omap44xx_kbd_hwmod, */ + &omap44xx_kbd_hwmod, /* mailbox class */ &omap44xx_mailbox_hwmod, @@ -5216,7 +5562,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_mcbsp4_hwmod, /* mcpdm class */ -/* &omap44xx_mcpdm_hwmod, */ + &omap44xx_mcpdm_hwmod, /* mcspi class */ &omap44xx_mcspi1_hwmod, diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h index c784c12..903310f 100644 --- a/arch/arm/mach-omap2/omap_opp_data.h +++ b/arch/arm/mach-omap2/omap_opp_data.h @@ -49,6 +49,8 @@ */ struct omap_opp_def { char *hwmod_name; + char *voltdm_name; + char *clk_name; unsigned long freq; unsigned long u_volt; @@ -59,9 +61,11 @@ struct omap_opp_def { /* * Initialization wrapper used to define an OPP for OMAP variants. */ -#define OPP_INITIALIZER(_hwmod_name, _enabled, _freq, _uv) \ +#define OPP_INITIALIZER(_hwmod_name, _clk_name, _voltdm_name, _enabled, _freq, _uv) \ { \ .hwmod_name = _hwmod_name, \ + .clk_name = _clk_name, \ + .voltdm_name = _voltdm_name, \ .default_available = _enabled, \ .freq = _freq, \ .u_volt = _uv, \ @@ -86,11 +90,21 @@ extern int __init omap_init_opp_table(struct omap_opp_def *opp_def, extern struct omap_volt_data omap34xx_vddmpu_volt_data[]; extern struct omap_volt_data omap34xx_vddcore_volt_data[]; +extern struct omap_vdd_dep_info omap34xx_vddmpu_dep_info[]; extern struct omap_volt_data omap36xx_vddmpu_volt_data[]; extern struct omap_volt_data omap36xx_vddcore_volt_data[]; +extern struct omap_vdd_dep_info omap36xx_vddmpu_dep_info[]; -extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[]; -extern struct omap_volt_data omap44xx_vdd_iva_volt_data[]; -extern struct omap_volt_data omap44xx_vdd_core_volt_data[]; +extern struct omap_volt_data omap443x_vdd_mpu_volt_data[]; +extern struct omap_volt_data omap443x_vdd_iva_volt_data[]; +extern struct omap_volt_data omap443x_vdd_core_volt_data[]; +extern struct omap_volt_data omap446x_vdd_mpu_volt_data[]; +extern struct omap_volt_data omap446x_vdd_iva_volt_data[]; +extern struct omap_volt_data omap446x_vdd_core_volt_data[]; + +extern struct omap_vdd_dep_info omap443x_vddmpu_dep_info[]; +extern struct omap_vdd_dep_info omap443x_vddiva_dep_info[]; +extern struct omap_vdd_dep_info omap446x_vddmpu_dep_info[]; +extern struct omap_vdd_dep_info omap446x_vddiva_dep_info[]; #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */ diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c index f47813e..58775e3 100644 --- a/arch/arm/mach-omap2/omap_phy_internal.c +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -56,8 +56,10 @@ int omap4430_phy_init(struct device *dev) /* Power down the phy */ __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); - if (!dev) + if (!dev) { + iounmap(ctrl_base); return 0; + } phyclk = clk_get(dev, "ocp2scp_usb_phy_ick"); if (IS_ERR(phyclk)) { diff --git a/arch/arm/mach-omap2/omap_pmic.c b/arch/arm/mach-omap2/omap_pmic.c new file mode 100644 index 0000000..ddf1b9d --- /dev/null +++ b/arch/arm/mach-omap2/omap_pmic.c @@ -0,0 +1,75 @@ +/* + * Registration hooks for PMICs used with OMAP + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> + +#include "voltage.h" + +#include "pm.h" + +/** + * omap_pmic_data_init() - trigger point for all PMIC initializers + */ +void __init omap_pmic_data_init(void) +{ + omap_twl_init(); + omap_tps6236x_init(); +} + +/** + * omap_pmic_register_data() - Register the PMIC information to OMAP mapping + * @omap_pmic_maps: array ending with a empty element representing the maps + */ +int __init omap_pmic_register_data(struct omap_pmic_map *omap_pmic_maps) +{ + struct voltagedomain *voltdm; + struct omap_pmic_map *map; + int r; + + if (!omap_pmic_maps) + return 0; + + map = omap_pmic_maps; + + while (map->name) { + if (!omap_chip_is(map->omap_chip)) + goto next; + + voltdm = voltdm_lookup(map->name); + if (IS_ERR_OR_NULL(voltdm)) { + pr_err("%s: unable to find map %s\n", __func__, + map->name); + goto next; + } + if (IS_ERR_OR_NULL(map->pmic_data)) { + pr_warning("%s: domain[%s] has no pmic data\n", + __func__, map->name); + goto next; + } + + r = omap_voltage_register_pmic(voltdm, map->pmic_data); + if (r) { + pr_warning("%s: domain[%s] register returned %d\n", + __func__, map->name, r); + goto next; + } + if (map->special_action) { + r = map->special_action(voltdm); + WARN(r, "%s: domain[%s] action returned %d\n", __func__, + map->name, r); + } +next: + map++; + } + + return 0; +} diff --git a/arch/arm/mach-omap2/omap_tps6236x.c b/arch/arm/mach-omap2/omap_tps6236x.c new file mode 100644 index 0000000..808d05c --- /dev/null +++ b/arch/arm/mach-omap2/omap_tps6236x.c @@ -0,0 +1,340 @@ +/* + * OMAP and TPS6236x specific initialization + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Vishwanath BS + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/i2c/twl.h> + +#include "pm.h" +#include "vc.h" +#include "mux.h" + +/* Voltage limits supported */ +#define MIN_VOLTAGE_TPS62360_62_UV 770000 +#define MAX_VOLTAGE_TPS62360_62_UV 1400000 + +#define MIN_VOLTAGE_TPS62361_UV 500000 +#define MAX_VOLTAGE_TPS62361_UV 1770000 + +#define MAX_VOLTAGE_RAMP_TPS6236X_UV 32000 + +/* + * This is the voltage delta between 2 values in voltage register. + * when switching voltage V1 to V2, TPS62361 can ramp up or down + * initially with step sizes of 20mV with a last step of 10mV. + * In the case of TPS6236[0|2], it is a constant 10mV steps + * we choose the 10mV step for linearity when SR is configured. + */ +#define STEP_SIZE_TPS6236X 10000 + +/* I2C access parameters */ +#define I2C_TPS6236X_SLAVE_ADDR 0x60 + +#define DEF_SET_REG(VSEL0, VSEL1) (((VSEL1) << 1| (VSEL0) << 0) & 0x3) +#define REG_TPS6236X_SET_0 0x00 +#define REG_TPS6236X_SET_1 0x01 +#define REG_TPS6236X_SET_2 0x02 +#define REG_TPS6236X_SET_3 0x03 +#define REG_TPS6236X_CTRL 0x04 +#define REG_TPS6236X_TEMP 0x05 +#define REG_TPS6236X_RAMP_CTRL 0x06 +#define REG_TPS6236X_CHIP_ID0 0x08 +#define REG_TPS6236X_CHIP_ID1 0x09 + +#define MODE_TPS6236X_AUTO_PFM_PWM 0x00 +#define MODE_TPS6236X_FORCE_PWM BIT(7) + +/* We use Auto PFM/PWM mode currently seems to have the best trade off */ +#define VOLTAGE_PFM_MODE_VAL MODE_TPS6236X_AUTO_PFM_PWM + +#define REG_TPS6236X_RAMP_CTRL_RMP_MASK (0x7 << 5) +#define REG_TPS6236X_RAMP_CTRL_EN_DISC BIT(2) +#define REG_TPS6236X_RAMP_CTRL_RAMP_PFM BIT(1) + +#define REG_TPS6236X_CTRL_PD_EN BIT(7) +#define REG_TPS6236X_CTRL_PD_VSEL0 BIT(6) +#define REG_TPS6236X_CTRL_PD_VSEL1 BIT(5) + +/* TWL usage */ +#define TWL6030_REG_SYSEN_CFG_GRP 0xB3 +#define TWL6030_BIT_APE_GRP BIT(0) + +/* Voltage params of the attached device (all in uV) */ +static unsigned long voltage_min; +static unsigned long voltage_max; + +/* Which register do we use by default? */ +static int __initdata default_reg = -1;; + +/* Do we need to setup internal pullups? */ +static int __initdata pd_vsel0 = -1; +static int __initdata pd_vsel1 = -1; + +static int __init _bd_setup(char *name,int gpio_vsel, int *pull, int *pd_vsel) +{ + int pull_dir; + int r; + + if (gpio_vsel == -1) { + if (*pull != -1) { + *pd_vsel = (*pull == OMAP_PIN_OFF_OUTPUT_HIGH); + *pull = *pd_vsel; + } else { + *pull = 0; + } + return 0; + } + + /* if we have a pull gpio, with bad dir, pull low */ + if (*pull == -1 || (*pull != OMAP_PIN_OFF_OUTPUT_HIGH && + *pull != OMAP_PIN_OFF_OUTPUT_LOW)) + *pull = OMAP_PIN_OFF_OUTPUT_LOW; + + r = omap_mux_init_gpio(gpio_vsel, *pull); + if (r) { + pr_err("%s: unable to mux gpio%d=%d\n", __func__, + gpio_vsel, r); + goto out; + } + + pull_dir = (*pull == OMAP_PIN_OFF_OUTPUT_HIGH); + *pull = pull_dir; + + r = gpio_request(gpio_vsel, name); + if (r) { + pr_err("%s: unable to req gpio%d=%d\n", __func__, + gpio_vsel, r); + goto out; + } + r = gpio_direction_output(gpio_vsel, pull_dir); + if (r) { + pr_err("%s: unable to pull[%d] gpio%d=%d\n", __func__, + gpio_vsel, pull_dir, r); + gpio_free(gpio_vsel); + goto out; + } +out: + return r; +} + +/* Convert the ramp voltage to ramp value. */ +static u8 __init tps6236x_ramp_value(unsigned long uv) +{ + if (!uv) + return 0; + + if (uv > MAX_VOLTAGE_RAMP_TPS6236X_UV) { + pr_err("%s: uv%ld greater than max %d\n", __func__, + uv, MAX_VOLTAGE_RAMP_TPS6236X_UV); + uv = MAX_VOLTAGE_RAMP_TPS6236X_UV; + } + return fls(MAX_VOLTAGE_RAMP_TPS6236X_UV / uv) - 1; +} + +static unsigned long tps6236x_vsel_to_uv(const u8 vsel) +{ + return (voltage_min + + (STEP_SIZE_TPS6236X * (vsel & ~VOLTAGE_PFM_MODE_VAL))); +} + +static u8 tps6236x_uv_to_vsel(unsigned long uv) +{ + if (!uv) + return 0; + + /* Round off requests to limits */ + if (uv > voltage_max) { + pr_err("%s:Request for overvoltage[%ld] than supported[%ld]\n", + __func__, uv, voltage_max); + uv = voltage_max; + } + if (uv < voltage_min) { + pr_err("%s:Request for undervoltage[%ld] than supported[%ld]\n", + __func__, uv, voltage_min); + uv = voltage_min; + } + return DIV_ROUND_UP(uv - voltage_min, STEP_SIZE_TPS6236X) | + VOLTAGE_PFM_MODE_VAL; +} + +static struct omap_voltdm_pmic omap4_mpu_pmic = { + .slew_rate = 8000, + .step_size = STEP_SIZE_TPS6236X, + .on_volt = 1375000, + .onlp_volt = 1375000, + .ret_volt = 830000, + .off_volt = 0, + .volt_setup_time = 0, + .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, + .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, + .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, + .vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN, + .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX, + .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, + .i2c_slave_addr = I2C_TPS6236X_SLAVE_ADDR, + .volt_reg_addr = REG_TPS6236X_SET_0, + .cmd_reg_addr = REG_TPS6236X_SET_0, + .i2c_high_speed = true, + .i2c_scll_low = 0x28, + .i2c_scll_high = 0x2C, + .i2c_hscll_low = 0x0B, + .i2c_hscll_high = 0x00, + .vsel_to_uv = tps6236x_vsel_to_uv, + .uv_to_vsel = tps6236x_uv_to_vsel, +}; + +/** + * omap4_twl_tps62361_enable() - Enable tps chip + * + * This function enables TPS chip by associating SYSEN signal + * to APE resource group of TWL6030. + * + * Returns 0 on sucess, error is returned if I2C read/write fails. + */ +static int __init omap4_twl_tps62361_enable(struct voltagedomain *voltdm) +{ + int ret = 0; + u8 val; + + /* Dont trust the bootloader. start with max, pm will set to proper */ + val = voltdm->pmic->uv_to_vsel(voltdm->pmic->vp_vddmax); + ret = omap_vc_bypass_send_i2c_msg(voltdm, voltdm->pmic->i2c_slave_addr, + default_reg, val); + + /* Setup Ramp */ + val = tps6236x_ramp_value(voltdm->pmic->slew_rate) << + __ffs(REG_TPS6236X_RAMP_CTRL_RMP_MASK); + val &= REG_TPS6236X_RAMP_CTRL_RMP_MASK; + + /* We would like to ramp the voltage asap */ + val |= REG_TPS6236X_RAMP_CTRL_RAMP_PFM; + + ret = omap_vc_bypass_send_i2c_msg(voltdm, voltdm->pmic->i2c_slave_addr, + REG_TPS6236X_RAMP_CTRL, val); + if (ret) + goto out; + + /* Setup the internal pulls to select if needed */ + if (pd_vsel0 != -1 || pd_vsel1 != -1) { + val = REG_TPS6236X_CTRL_PD_EN; + val |= (pd_vsel0) ? 0 : REG_TPS6236X_CTRL_PD_VSEL0; + val |= (pd_vsel1) ? 0 : REG_TPS6236X_CTRL_PD_VSEL1; + ret = omap_vc_bypass_send_i2c_msg(voltdm, + voltdm->pmic->i2c_slave_addr, + REG_TPS6236X_CTRL, val); + if (ret) + goto out; + } + + /* Enable thermal shutdown - 0 is enable :) */ + ret = omap_vc_bypass_send_i2c_msg(voltdm, + voltdm->pmic->i2c_slave_addr, + REG_TPS6236X_TEMP, 0x0); + if (ret) + goto out; + + /* if we have to work with TWL */ +#ifdef CONFIG_TWL4030_CORE + ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &val, + TWL6030_REG_SYSEN_CFG_GRP); + if (ret) + goto out; + + val |= TWL6030_BIT_APE_GRP; + ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, val, + TWL6030_REG_SYSEN_CFG_GRP); +#endif + +out: + if (ret) + pr_err("%s: Error enabling TPS(%d)\n", __func__, ret); + + return ret; +} + +static __initdata struct omap_pmic_map omap_tps_map[] = { + { + .name = "mpu", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), + .pmic_data = &omap4_mpu_pmic, + .special_action = omap4_twl_tps62361_enable, + }, + /* Terminator */ + { .name = NULL,.pmic_data = NULL}, +}; + +int __init omap_tps6236x_init(void) +{ + struct omap_pmic_map *map; + + /* Without registers, I wont proceed */ + if (default_reg == -1) + return -EINVAL; + + map = omap_tps_map; + + /* setup all the pmic's voltage addresses to the default one */ + while (map->name) { + map->pmic_data->volt_reg_addr = default_reg; + map->pmic_data->cmd_reg_addr = default_reg; + map++; + } + + return omap_pmic_register_data(omap_tps_map); +} + +/** + * omap_tps6236x_board_setup() - provide the board config for TPS connect + * @use_62361: Do we use TPS62361 variant? + * @gpio_vsel0: If using GPIO to control VSEL0, provide gpio number, else -1 + * @gpio_vsel1: If using GPIO to control VSEL1, provide gpio number, else -1 + * @pull0: If using GPIO, provide mux mode OMAP_PIN_OFF_OUTPUT_[HIGH|LOW] + * else provide any internal pull required, -1 if unused. + * @pull1: If using GPIO, provide mux mode OMAP_PIN_OFF_OUTPUT_[HIGH|LOW] + * else provide any internal pull required, -1 if unused. + * + * TPS6236x variants of PMIC can be hooked in numerous combinations on to the + * board. Some platforms can choose to hardwire and save on a GPIO for other + * uses, while others may hook a single line for GPIO control and may ground + * the other line. support these configurations. + * + * WARNING: for platforms using GPIO, be careful to provide MUX setting + * considering OFF mode configuration as well. + */ +int __init omap_tps6236x_board_setup(bool use_62361, int gpio_vsel0, + int gpio_vsel1, int pull0, int pull1) +{ + int r; + + r = _bd_setup("tps6236x_vsel0", gpio_vsel0, &pull0, &pd_vsel0); + if (r) + goto out; + r = _bd_setup("tps6236x_vsel1", gpio_vsel1, &pull1, &pd_vsel1); + if (r) { + if (gpio_vsel0 != -1) + gpio_free(gpio_vsel0); + goto out; + } + + default_reg = ((pull1 & 0x1) << 1) | (pull0 & 0x1); + + if (use_62361) { + voltage_min = MIN_VOLTAGE_TPS62361_UV; + voltage_max = MAX_VOLTAGE_TPS62361_UV; + } else { + voltage_min = MIN_VOLTAGE_TPS62360_62_UV; + voltage_max = MAX_VOLTAGE_TPS62360_62_UV; + } +out: + return r; +} diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index 07d6140..0e30412 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c @@ -30,32 +30,13 @@ #define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04 #define OMAP3_VP_VLIMITTO_TIMEOUT_US 200 -#define OMAP3430_VP1_VLIMITTO_VDDMIN 0x14 -#define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42 -#define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18 -#define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c - -#define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18 -#define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c -#define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18 -#define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30 - #define OMAP4_SRI2C_SLAVE_ADDR 0x12 #define OMAP4_VDD_MPU_SR_VOLT_REG 0x55 +#define OMAP4_VDD_MPU_SR_CMD_REG 0x56 #define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B +#define OMAP4_VDD_IVA_SR_CMD_REG 0x5C #define OMAP4_VDD_CORE_SR_VOLT_REG 0x61 - -#define OMAP4_VP_CONFIG_ERROROFFSET 0x00 -#define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01 -#define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04 -#define OMAP4_VP_VLIMITTO_TIMEOUT_US 200 - -#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA -#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39 -#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA -#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D -#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA -#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28 +#define OMAP4_VDD_CORE_SR_CMD_REG 0x62 static bool is_offset_valid; static u8 smps_offset; @@ -95,6 +76,8 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel) is_offset_valid = true; } + if (!vsel) + return 0; /* * There is no specific formula for voltage to vsel * conversion above 1.3V. There are special hardcoded @@ -106,9 +89,9 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel) return 1350000; if (smps_offset & 0x8) - return ((((vsel - 1) * 125) + 7000)) * 100; + return ((((vsel - 1) * 1266) + 70900)) * 10; else - return ((((vsel - 1) * 125) + 6000)) * 100; + return ((((vsel - 1) * 1266) + 60770)) * 10; } static u8 twl6030_uv_to_vsel(unsigned long uv) @@ -127,6 +110,8 @@ static u8 twl6030_uv_to_vsel(unsigned long uv) is_offset_valid = true; } + if (!uv) + return 0x00; /* * There is no specific formula for voltage to vsel * conversion above 1.3V. There are special hardcoded @@ -134,16 +119,21 @@ static u8 twl6030_uv_to_vsel(unsigned long uv) * hardcoding only for 1.35 V which is used for 1GH OPP for * OMAP4430. */ - if (uv == 1350000) + if (uv > twl6030_vsel_to_uv(0x39)) { + if (uv == 1350000) + return 0x3A; + pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n", + __func__, uv, twl6030_vsel_to_uv(0x39)); return 0x3A; + } if (smps_offset & 0x8) - return DIV_ROUND_UP(uv - 700000, 12500) + 1; + return DIV_ROUND_UP(uv - 709000, 12660) + 1; else - return DIV_ROUND_UP(uv - 600000, 12500) + 1; + return DIV_ROUND_UP(uv - 607700, 12660) + 1; } -static struct omap_volt_pmic_info omap3_mpu_volt_info = { +static struct omap_voltdm_pmic omap3_mpu_pmic = { .slew_rate = 4000, .step_size = 12500, .on_volt = 1200000, @@ -158,12 +148,13 @@ static struct omap_volt_pmic_info omap3_mpu_volt_info = { .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX, .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, - .pmic_reg = OMAP3_VDD_MPU_SR_CONTROL_REG, + .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG, + .i2c_high_speed = true, .vsel_to_uv = twl4030_vsel_to_uv, .uv_to_vsel = twl4030_uv_to_vsel, }; -static struct omap_volt_pmic_info omap3_core_volt_info = { +static struct omap_voltdm_pmic omap3_core_pmic = { .slew_rate = 4000, .step_size = 12500, .on_volt = 1200000, @@ -178,18 +169,19 @@ static struct omap_volt_pmic_info omap3_core_volt_info = { .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX, .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, - .pmic_reg = OMAP3_VDD_CORE_SR_CONTROL_REG, + .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG, + .i2c_high_speed = true, .vsel_to_uv = twl4030_vsel_to_uv, .uv_to_vsel = twl4030_uv_to_vsel, }; -static struct omap_volt_pmic_info omap4_mpu_volt_info = { +static struct omap_voltdm_pmic omap443x_mpu_pmic = { .slew_rate = 4000, - .step_size = 12500, - .on_volt = 1350000, - .onlp_volt = 1350000, - .ret_volt = 837500, - .off_volt = 600000, + .step_size = 12660, + .on_volt = 1375000, + .onlp_volt = 1375000, + .ret_volt = 830000, + .off_volt = 0, .volt_setup_time = 0, .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, @@ -198,18 +190,24 @@ static struct omap_volt_pmic_info omap4_mpu_volt_info = { .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX, .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, - .pmic_reg = OMAP4_VDD_MPU_SR_VOLT_REG, + .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG, + .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG, + .i2c_high_speed = true, + .i2c_scll_low = 0x28, + .i2c_scll_high = 0x2C, + .i2c_hscll_low = 0x0B, + .i2c_hscll_high = 0x00, .vsel_to_uv = twl6030_vsel_to_uv, .uv_to_vsel = twl6030_uv_to_vsel, }; -static struct omap_volt_pmic_info omap4_iva_volt_info = { +static struct omap_voltdm_pmic omap4_iva_pmic = { .slew_rate = 4000, - .step_size = 12500, - .on_volt = 1100000, - .onlp_volt = 1100000, - .ret_volt = 837500, - .off_volt = 600000, + .step_size = 12660, + .on_volt = 1188000, + .onlp_volt = 1188000, + .ret_volt = 830000, + .off_volt = 0, .volt_setup_time = 0, .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, @@ -218,18 +216,24 @@ static struct omap_volt_pmic_info omap4_iva_volt_info = { .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX, .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, - .pmic_reg = OMAP4_VDD_IVA_SR_VOLT_REG, + .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG, + .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG, + .i2c_high_speed = true, + .i2c_scll_low = 0x28, + .i2c_scll_high = 0x2C, + .i2c_hscll_low = 0x0B, + .i2c_hscll_high = 0x00, .vsel_to_uv = twl6030_vsel_to_uv, .uv_to_vsel = twl6030_uv_to_vsel, }; -static struct omap_volt_pmic_info omap4_core_volt_info = { +static struct omap_voltdm_pmic omap443x_core_pmic = { .slew_rate = 4000, - .step_size = 12500, - .on_volt = 1100000, - .onlp_volt = 1100000, - .ret_volt = 837500, - .off_volt = 600000, + .step_size = 12660, + .on_volt = 1200000, + .onlp_volt = 1200000, + .ret_volt = 830000, + .off_volt = 0, .volt_setup_time = 0, .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, @@ -238,43 +242,47 @@ static struct omap_volt_pmic_info omap4_core_volt_info = { .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX, .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, - .pmic_reg = OMAP4_VDD_CORE_SR_VOLT_REG, + .i2c_high_speed = true, + .i2c_scll_low = 0x28, + .i2c_scll_high = 0x2C, + .i2c_hscll_low = 0x0B, + .i2c_hscll_high = 0x00, + .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG, + .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG, .vsel_to_uv = twl6030_vsel_to_uv, .uv_to_vsel = twl6030_uv_to_vsel, }; -int __init omap4_twl_init(void) -{ - struct voltagedomain *voltdm; - - if (!cpu_is_omap44xx()) - return -ENODEV; - - voltdm = omap_voltage_domain_lookup("mpu"); - omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info); - - voltdm = omap_voltage_domain_lookup("iva"); - omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info); - - voltdm = omap_voltage_domain_lookup("core"); - omap_voltage_register_pmic(voltdm, &omap4_core_volt_info); - - return 0; -} +/* Core uses the MPU rail of 4430 */ +static struct omap_voltdm_pmic omap446x_core_pmic = { + .slew_rate = 4000, + .step_size = 12660, + .on_volt = 1200000, + .onlp_volt = 1200000, + .ret_volt = 830000, + .off_volt = 0, + .volt_setup_time = 0, + .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, + .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, + .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, + .vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN, + .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX, + .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, + .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, + .i2c_high_speed = true, + .i2c_scll_low = 0x28, + .i2c_scll_high = 0x2C, + .i2c_hscll_low = 0x0B, + .i2c_hscll_high = 0x00, + .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG, + .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG, + .vsel_to_uv = twl6030_vsel_to_uv, + .uv_to_vsel = twl6030_uv_to_vsel, +}; -int __init omap3_twl_init(void) +static int __init twl_set_sr(struct voltagedomain *voltdm) { - struct voltagedomain *voltdm; - - if (!cpu_is_omap34xx()) - return -ENODEV; - - if (cpu_is_omap3630()) { - omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; - omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; - omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; - omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; - } + int r = 0; /* * The smartreflex bit on twl4030 specifies if the setting of voltage @@ -286,15 +294,61 @@ int __init omap3_twl_init(void) * voltage scaling will not function on TWL over I2C_SR. */ if (!twl_sr_enable_autoinit) - omap3_twl_set_sr_bit(true); + r = omap3_twl_set_sr_bit(true); + return r; +} - voltdm = omap_voltage_domain_lookup("mpu"); - omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); +#define OMAP3_TWL4030_USED (CHIP_GE_OMAP3430ES2 | \ + CHIP_GE_OMAP3630ES1_1 | \ + CHIP_IS_OMAP3630ES1) + +static __initdata struct omap_pmic_map omap_twl_map[] = { + { + .name = "mpu_iva", + .omap_chip = OMAP_CHIP_INIT(OMAP3_TWL4030_USED), + .pmic_data = &omap3_mpu_pmic, + .special_action = twl_set_sr, + }, + { + .name = "core", + .omap_chip = OMAP_CHIP_INIT(OMAP3_TWL4030_USED), + .pmic_data = &omap3_core_pmic, + }, + { + .name = "mpu", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP443X), + .pmic_data = &omap443x_mpu_pmic, + }, + { + .name = "core", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP443X), + .pmic_data = &omap443x_core_pmic, + }, + { + .name = "core", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), + .pmic_data = &omap446x_core_pmic, + }, + { + .name = "iva", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pmic_data = &omap4_iva_pmic, + }, + /* Terminator */ + { .name = NULL, .pmic_data = NULL}, +}; - voltdm = omap_voltage_domain_lookup("core"); - omap_voltage_register_pmic(voltdm, &omap3_core_volt_info); +int __init omap_twl_init(void) +{ + /* Reuse OMAP3430 values */ + if (cpu_is_omap3630()) { + omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; + omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; + omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; + omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; + } - return 0; + return omap_pmic_register_data(omap_twl_map); } /** diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index ab8b35b..1952854 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -22,6 +22,7 @@ #include <plat/omap_device.h> #include "omap_opp_data.h" +#include "dvfs.h" /* Temp variable to allow multiple calls */ static u8 __initdata omap_table_init; @@ -58,16 +59,16 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, struct device *dev; if (!opp_def->hwmod_name) { - pr_err("%s: NULL name of omap_hwmod, failing [%d].\n", - __func__, i); - return -EINVAL; + WARN(1, "%s: NULL name of omap_hwmod, failing" + " [%d].\n", __func__, i); + goto next; } oh = omap_hwmod_lookup(opp_def->hwmod_name); if (!oh || !oh->od) { - pr_warn("%s: no hwmod or odev for %s, [%d] " + WARN(1, "%s: no hwmod or odev for %s, [%d] " "cannot add OPPs.\n", __func__, opp_def->hwmod_name, i); - return -EINVAL; + goto next; } dev = &oh->od->pdev.dev; @@ -85,7 +86,14 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, "[%d] result=%d\n", __func__, opp_def->freq, opp_def->hwmod_name, i, r); + + r = omap_dvfs_register_device(dev, + opp_def->voltdm_name, opp_def->clk_name); + if (r) + dev_err(dev, "%s:%s:err dvfs register %d %d\n", + __func__, opp_def->hwmod_name, r, i); } +next: opp_def++; } diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c index d95f3f9..7662662 100644 --- a/arch/arm/mach-omap2/opp3xxx_data.c +++ b/arch/arm/mach-omap2/opp3xxx_data.c @@ -57,6 +57,24 @@ struct omap_volt_data omap34xx_vddcore_volt_data[] = { VOLT_DATA_DEFINE(0, 0, 0, 0), }; +/* OMAP 3430 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap34xx_vdd_mpu_core_dep_data[] = { + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP1_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP2_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP2_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP2_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP3_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP3_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP4_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP3_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP5_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP3_UV}, +}; + +struct omap_vdd_dep_info omap34xx_vddmpu_dep_info[] = { + { + .name = "core", + .dep_table = omap34xx_vdd_mpu_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap34xx_vdd_mpu_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; + /* 36xx */ /* VDD1 */ @@ -89,15 +107,15 @@ struct omap_volt_data omap36xx_vddcore_volt_data[] = { static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { /* MPU OPP1 */ - OPP_INITIALIZER("mpu", true, 125000000, OMAP3430_VDD_MPU_OPP1_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 125000000, OMAP3430_VDD_MPU_OPP1_UV), /* MPU OPP2 */ - OPP_INITIALIZER("mpu", true, 250000000, OMAP3430_VDD_MPU_OPP2_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 250000000, OMAP3430_VDD_MPU_OPP2_UV), /* MPU OPP3 */ - OPP_INITIALIZER("mpu", true, 500000000, OMAP3430_VDD_MPU_OPP3_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 500000000, OMAP3430_VDD_MPU_OPP3_UV), /* MPU OPP4 */ - OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV), /* MPU OPP5 */ - OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV), /* * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is @@ -107,47 +125,64 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { * impact that frequency will do to the MPU and the whole system in * general. */ - OPP_INITIALIZER("l3_main", false, 41500000, OMAP3430_VDD_CORE_OPP1_UV), + OPP_INITIALIZER("l3_main", "dpll3_ck", "core", false, 41500000, OMAP3430_VDD_CORE_OPP1_UV), /* L3 OPP2 */ - OPP_INITIALIZER("l3_main", true, 83000000, OMAP3430_VDD_CORE_OPP2_UV), + OPP_INITIALIZER("l3_main", "dpll3_ck", "core", true, 83000000, OMAP3430_VDD_CORE_OPP2_UV), /* L3 OPP3 */ - OPP_INITIALIZER("l3_main", true, 166000000, OMAP3430_VDD_CORE_OPP3_UV), + OPP_INITIALIZER("l3_main", "dpll3_ck", "core", true, 166000000, OMAP3430_VDD_CORE_OPP3_UV), /* DSP OPP1 */ - OPP_INITIALIZER("iva", true, 90000000, OMAP3430_VDD_MPU_OPP1_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 90000000, OMAP3430_VDD_MPU_OPP1_UV), /* DSP OPP2 */ - OPP_INITIALIZER("iva", true, 180000000, OMAP3430_VDD_MPU_OPP2_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 180000000, OMAP3430_VDD_MPU_OPP2_UV), /* DSP OPP3 */ - OPP_INITIALIZER("iva", true, 360000000, OMAP3430_VDD_MPU_OPP3_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 360000000, OMAP3430_VDD_MPU_OPP3_UV), /* DSP OPP4 */ - OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV), /* DSP OPP5 */ - OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV), }; static struct omap_opp_def __initdata omap36xx_opp_def_list[] = { /* MPU OPP1 - OPP50 */ - OPP_INITIALIZER("mpu", true, 300000000, OMAP3630_VDD_MPU_OPP50_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 300000000, OMAP3630_VDD_MPU_OPP50_UV), /* MPU OPP2 - OPP100 */ - OPP_INITIALIZER("mpu", true, 600000000, OMAP3630_VDD_MPU_OPP100_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", true, 600000000, OMAP3630_VDD_MPU_OPP100_UV), /* MPU OPP3 - OPP-Turbo */ - OPP_INITIALIZER("mpu", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV), /* MPU OPP4 - OPP-SB */ - OPP_INITIALIZER("mpu", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV), + OPP_INITIALIZER("mpu", "dpll1_ck", "mpu_iva", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV), /* L3 OPP1 - OPP50 */ - OPP_INITIALIZER("l3_main", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV), + OPP_INITIALIZER("l3_main", "dpll3_ck", "core", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ - OPP_INITIALIZER("l3_main", true, 200000000, OMAP3630_VDD_CORE_OPP100_UV), + OPP_INITIALIZER("l3_main", "dpll3_ck", "core", true, 200000000, OMAP3630_VDD_CORE_OPP100_UV), /* DSP OPP1 - OPP50 */ - OPP_INITIALIZER("iva", true, 260000000, OMAP3630_VDD_MPU_OPP50_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 260000000, OMAP3630_VDD_MPU_OPP50_UV), /* DSP OPP2 - OPP100 */ - OPP_INITIALIZER("iva", true, 520000000, OMAP3630_VDD_MPU_OPP100_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", true, 520000000, OMAP3630_VDD_MPU_OPP100_UV), /* DSP OPP3 - OPP-Turbo */ - OPP_INITIALIZER("iva", false, 660000000, OMAP3630_VDD_MPU_OPP120_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", false, 660000000, OMAP3630_VDD_MPU_OPP120_UV), /* DSP OPP4 - OPP-SB */ - OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV), + OPP_INITIALIZER("iva", "dpll2_ck", "mpu_iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV), +}; + +/* OMAP 3630 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap36xx_vdd_mpu_core_dep_data[] = { + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP50_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP100_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP120_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP1G_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap36xx_vddmpu_dep_info[] = { + { + .name = "core", + .dep_table = omap36xx_vdd_mpu_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap36xx_vdd_mpu_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, }; /** diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index 2293ba2..8d14e2f 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -1,7 +1,7 @@ /* * OMAP4 OPP table definitions. * - * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ * Nishanth Menon * Kevin Hilman * Thara Gopinath @@ -36,7 +36,7 @@ #define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000 #define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000 -struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = { +struct omap_volt_data omap443x_vdd_mpu_volt_data[] = { VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c), VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16), VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23), @@ -48,7 +48,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = { #define OMAP4430_VDD_IVA_OPP100_UV 1188000 #define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000 -struct omap_volt_data omap44xx_vdd_iva_volt_data[] = { +struct omap_volt_data omap443x_vdd_iva_volt_data[] = { VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c), VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16), VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23), @@ -58,33 +58,194 @@ struct omap_volt_data omap44xx_vdd_iva_volt_data[] = { #define OMAP4430_VDD_CORE_OPP50_UV 1025000 #define OMAP4430_VDD_CORE_OPP100_UV 1200000 -struct omap_volt_data omap44xx_vdd_core_volt_data[] = { +struct omap_volt_data omap443x_vdd_core_volt_data[] = { VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c), VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16), VOLT_DATA_DEFINE(0, 0, 0, 0), }; +/* Dependency of domains are as follows for OMAP4430 (OPP based): + * + * MPU IVA CORE + * 50 50 50+ + * 50 100+ 100 + * 100+ 50 100 + * 100+ 100+ 100 + */ + +/* OMAP 4430 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap443x_vdd_mpu_core_dep_data[] = { + {.main_vdd_volt = OMAP4430_VDD_MPU_OPP50_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP4430_VDD_MPU_OPP100_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4430_VDD_MPU_OPPTURBO_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4430_VDD_MPU_OPPNITRO_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap443x_vddmpu_dep_info[] = { + { + .name = "core", + .dep_table = omap443x_vdd_mpu_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap443x_vdd_mpu_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; -static struct omap_opp_def __initdata omap44xx_opp_def_list[] = { +/* OMAP 4430 MPU IVA VDD dependency table */ +static struct omap_vdd_dep_volt omap443x_vdd_iva_core_dep_data[] = { + {.main_vdd_volt = OMAP4430_VDD_IVA_OPP50_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP4430_VDD_IVA_OPP100_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4430_VDD_IVA_OPPTURBO_UV, .dep_vdd_volt = OMAP4430_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap443x_vddiva_dep_info[] = { + { + .name = "core", + .dep_table = omap443x_vdd_iva_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap443x_vdd_iva_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; + +static struct omap_opp_def __initdata omap443x_opp_def_list[] = { /* MPU OPP1 - OPP50 */ - OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV), + OPP_INITIALIZER("mpu", "dpll_mpu_ck", "mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV), /* MPU OPP2 - OPP100 */ - OPP_INITIALIZER("mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV), + OPP_INITIALIZER("mpu", "dpll_mpu_ck", "mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV), /* MPU OPP3 - OPP-Turbo */ - OPP_INITIALIZER("mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV), + OPP_INITIALIZER("mpu", "dpll_mpu_ck", "mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV), /* MPU OPP4 - OPP-SB */ - OPP_INITIALIZER("mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV), + OPP_INITIALIZER("mpu", "dpll_mpu_ck", "mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV), /* L3 OPP1 - OPP50 */ - OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV), + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ - OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV), + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV), /* IVA OPP1 - OPP50 */ - OPP_INITIALIZER("iva", true, 133000000, OMAP4430_VDD_IVA_OPP50_UV), + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 133000000, OMAP4430_VDD_IVA_OPP50_UV), /* IVA OPP2 - OPP100 */ - OPP_INITIALIZER("iva", true, 266100000, OMAP4430_VDD_IVA_OPP100_UV), + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 266100000, OMAP4430_VDD_IVA_OPP100_UV), /* IVA OPP3 - OPP-Turbo */ - OPP_INITIALIZER("iva", false, 332000000, OMAP4430_VDD_IVA_OPPTURBO_UV), - /* TODO: add DSP, aess, fdif, gpu */ + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", false, 332000000, OMAP4430_VDD_IVA_OPPTURBO_UV), + /* SGX OPP1 - OPP50 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 153600000, OMAP4430_VDD_CORE_OPP50_UV), + /* SGX OPP2 - OPP100 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 307200000, OMAP4430_VDD_CORE_OPP50_UV), + /* TODO: add DSP, aess, fdif */ +}; + +#define OMAP4460_VDD_MPU_OPP50_UV 1025000 +#define OMAP4460_VDD_MPU_OPP100_UV 1200000 +#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000 +#define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000 + +struct omap_volt_data omap446x_vdd_mpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23), + VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +#define OMAP4460_VDD_IVA_OPP50_UV 1025000 +#define OMAP4460_VDD_IVA_OPP100_UV 1200000 +#define OMAP4460_VDD_IVA_OPPTURBO_UV 1313000 +#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000 + +struct omap_volt_data omap446x_vdd_iva_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23), + VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +#define OMAP4460_VDD_CORE_OPP50_UV 1025000 +#define OMAP4460_VDD_CORE_OPP100_UV 1200000 +#define OMAP4460_VDD_CORE_OPP100_OV_UV 1250000 + +struct omap_volt_data omap446x_vdd_core_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* OMAP 4460 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap446x_vdd_mpu_core_dep_data[] = { + {.main_vdd_volt = OMAP4460_VDD_MPU_OPP50_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP4460_VDD_MPU_OPP100_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4460_VDD_MPU_OPPTURBO_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4460_VDD_MPU_OPPNITRO_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap446x_vddmpu_dep_info[] = { + { + .name = "core", + .dep_table = omap446x_vdd_mpu_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap446x_vdd_mpu_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; + +/* OMAP 4460 MPU IVA VDD dependency table */ +static struct omap_vdd_dep_volt omap446x_vdd_iva_core_dep_data[] = { + {.main_vdd_volt = OMAP4460_VDD_IVA_OPP50_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP4460_VDD_IVA_OPP100_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4460_VDD_IVA_OPPTURBO_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap446x_vddiva_dep_info[] = { + { + .name = "core", + .dep_table = omap446x_vdd_iva_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap446x_vdd_iva_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; + +static struct omap_opp_def __initdata omap446x_opp_def_list[] = { + /* MPU OPP1 - OPP50 */ + OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV), + /* MPU OPP2 - OPP100 */ + OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV), + /* MPU OPP3 - OPP-Turbo */ + OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV), + /* + * MPU OPP4 - OPP-Nitro + Disabled as the reference schematics + * recommends TPS623631 - confirm and enable the opp in board file + * XXX: May be we should enable these based on mpu capability and + * Exception board files disable it... + */ + OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV), + /* MPU OPP4 - OPP-Nitro SpeedBin */ + OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV), + /* L3 OPP1 - OPP50 */ + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV), + /* L3 OPP2 - OPP100 */ + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV), + /* IVA OPP1 - OPP50 */ + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV), + /* IVA OPP2 - OPP100 */ + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV), + /* + * IVA OPP3 - OPP-Turbo + Disabled as the reference schematics + * recommends Phoenix VCORE2 which can supply only 600mA - so the ones + * above this OPP frequency, even though OMAP is capable, should be + * enabled by board file which is sure of the chip power capability + */ + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV), + /* IVA OPP4 - OPP-Nitro */ + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV), + /* IVA OPP5 - OPP-Nitro SpeedBin*/ + OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV), + + /* SGX OPP1 - OPP50 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 153600000, OMAP4460_VDD_CORE_OPP50_UV), + /* SGX OPP2 - OPP100 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 307200000, OMAP4460_VDD_CORE_OPP100_UV), + /* SGX OPP3 - OPPOV */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 384000000, OMAP4460_VDD_CORE_OPP100_OV_UV), + + /* TODO: add DSP, aess, fdif */ }; /** @@ -96,10 +257,12 @@ int __init omap4_opp_init(void) if (!cpu_is_omap44xx()) return r; - - r = omap_init_opp_table(omap44xx_opp_def_list, - ARRAY_SIZE(omap44xx_opp_def_list)); - + if (cpu_is_omap443x()) + r = omap_init_opp_table(omap443x_opp_def_list, + ARRAY_SIZE(omap443x_opp_def_list)); + else if (cpu_is_omap446x()) + r = omap_init_opp_table(omap446x_opp_def_list, + ARRAY_SIZE(omap446x_opp_def_list)); return r; } device_initcall(omap4_opp_init); diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index a5a83b3..0ef8d69 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -189,7 +189,7 @@ static struct dentry *pm_dbg_dir; static int pm_dbg_init_done; -static int __init pm_dbg_init(void); +static int pm_dbg_init(void); enum { DEBUG_FILE_COUNTERS = 0, @@ -595,7 +595,7 @@ static int option_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n"); -static int __init pm_dbg_init(void) +static int pm_dbg_init(void) { int i; struct dentry *d; @@ -604,9 +604,11 @@ static int __init pm_dbg_init(void) if (pm_dbg_init_done) return 0; - if (cpu_is_omap34xx()) + if (cpu_is_omap34xx()) { pm_dbg_reg_modules = omap3_pm_reg_modules; - else { + } else if (cpu_is_omap44xx()) { + /* Allow pm_dbg_init on OMAP4. */ + } else { printk(KERN_ERR "%s: only OMAP3 supported\n", __func__); return -ENODEV; } @@ -622,6 +624,9 @@ static int __init pm_dbg_init(void) pwrdm_for_each(pwrdms_setup, (void *)d); + if (cpu_is_omap44xx()) + goto skip_reg_debufs; + pm_dbg_dir = debugfs_create_dir("registers", d); if (IS_ERR(pm_dbg_dir)) return PTR_ERR(pm_dbg_dir); @@ -641,6 +646,8 @@ static int __init pm_dbg_init(void) &enable_off_mode, &pm_dbg_option_fops); (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d, &sleep_while_idle, &pm_dbg_option_fops); + +skip_reg_debufs: (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d, &wakeup_timer_seconds, &pm_dbg_option_fops); (void) debugfs_create_file("wakeup_timer_milliseconds", diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 49486f5..744431c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -36,18 +36,21 @@ struct device *omap2_get_mpuss_device(void) WARN_ON_ONCE(!mpu_dev); return mpu_dev; } +EXPORT_SYMBOL(omap2_get_mpuss_device); struct device *omap2_get_iva_device(void) { WARN_ON_ONCE(!iva_dev); return iva_dev; } +EXPORT_SYMBOL(omap2_get_iva_device); struct device *omap2_get_l3_device(void) { WARN_ON_ONCE(!l3_dev); return l3_dev; } +EXPORT_SYMBOL(omap2_get_l3_device); struct device *omap4_get_dsp_device(void) { @@ -106,8 +109,9 @@ static void omap2_init_processor_devices(void) int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) { u32 cur_state; - int sleep_switch = 0; + int sleep_switch = -1; int ret = 0; + int hwsup = 0; if (pwrdm == NULL || IS_ERR(pwrdm)) return -EINVAL; @@ -127,6 +131,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { sleep_switch = LOWPOWERSTATE_SWITCH; } else { + hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]); clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); pwrdm_wait_transition(pwrdm); sleep_switch = FORCEWAKEUP_SWITCH; @@ -142,7 +147,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) switch (sleep_switch) { case FORCEWAKEUP_SWITCH: - if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) + if (hwsup) clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else clkdm_sleep(pwrdm->pwrdm_clkdms[0]); @@ -174,14 +179,15 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, struct voltagedomain *voltdm; struct clk *clk; struct opp *opp; - unsigned long freq, bootup_volt; + unsigned long freq_cur, freq_valid, bootup_volt; + int ret = -EINVAL; if (!vdd_name || !clk_name || !dev) { printk(KERN_ERR "%s: Invalid parameters!\n", __func__); goto exit; } - voltdm = omap_voltage_domain_lookup(vdd_name); + voltdm = voltdm_lookup(vdd_name); if (IS_ERR(voltdm)) { printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n", __func__, vdd_name); @@ -195,25 +201,78 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, goto exit; } - freq = clk->rate; - clk_put(clk); + freq_cur = clk->rate; + freq_valid = freq_cur; - opp = opp_find_freq_ceil(dev, &freq); + rcu_read_lock(); + opp = opp_find_freq_ceil(dev, &freq_valid); if (IS_ERR(opp)) { - printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n", - __func__, vdd_name); - goto exit; + opp = opp_find_freq_floor(dev, &freq_valid); + if (IS_ERR(opp)) { + rcu_read_unlock(); + pr_err("%s: no boot OPP match for %ld on vdd_%s\n", + __func__, freq_cur, vdd_name); + ret = -ENOENT; + goto exit_ck; + } } bootup_volt = opp_get_voltage(opp); + rcu_read_unlock(); if (!bootup_volt) { printk(KERN_ERR "%s: unable to find voltage corresponding" "to the bootup OPP for vdd_%s\n", __func__, vdd_name); - goto exit; + ret = -ENOENT; + goto exit_ck; } - omap_voltage_scale_vdd(voltdm, bootup_volt); - return 0; + /* + * Frequency and Voltage have to be sequenced: if we move from + * a lower frequency to higher frequency, raise voltage, followed by + * frequency, and vice versa. we assume that the voltage at boot + * is the required voltage for the frequency it was set for. + * NOTE: + * we can check the frequency, but there is numerous ways to set + * voltage. We play the safe path and just set the voltage. + */ + + if (freq_cur < freq_valid) { + ret = voltdm_scale(voltdm, bootup_volt); + if (ret) { + pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n", + __func__, vdd_name, freq_valid, + bootup_volt, vdd_name); + goto exit_ck; + } + } + + /* Set freq only if there is a difference in freq */ + if (freq_valid != freq_cur) { + ret = clk_set_rate(clk, freq_valid); + if (ret) { + pr_err("%s: Fail set clk-%s(f=%ld v=%ld)on vdd%s\n", + __func__, clk_name, freq_valid, + bootup_volt, vdd_name); + goto exit_ck; + } + } + + if (freq_cur >= freq_valid) { + ret = voltdm_scale(voltdm, bootup_volt); + if (ret) { + pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n", + __func__, clk_name, freq_valid, + bootup_volt, vdd_name); + goto exit_ck; + } + } + + ret = 0; +exit_ck: + clk_put(clk); + + if (!ret) + return 0; exit: printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n", @@ -226,7 +285,7 @@ static void __init omap3_init_voltages(void) if (!cpu_is_omap34xx()) return; - omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev); + omap2_set_init_voltage("mpu_iva", "dpll1_ck", mpu_dev); omap2_set_init_voltage("core", "l3_ick", l3_dev); } @@ -235,8 +294,13 @@ static void __init omap4_init_voltages(void) if (!cpu_is_omap44xx()) return; - omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev); - omap2_set_init_voltage("core", "l3_div_ck", l3_dev); + if (cpu_is_omap446x()) { + omap2_set_init_voltage("mpu", "virt_dpll_mpu_ck", mpu_dev); + omap2_set_init_voltage("core", "virt_l3_ck", l3_dev); + } else { + omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev); + omap2_set_init_voltage("core", "l3_div_ck", l3_dev); + } omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev); } @@ -251,9 +315,8 @@ postcore_initcall(omap2_common_pm_init); static int __init omap2_common_pm_late_init(void) { - /* Init the OMAP TWL parameters */ - omap3_twl_init(); - omap4_twl_init(); + /* Init the OMAP PMIC parameters */ + omap_pmic_data_init(); /* Init the voltage layer */ omap_voltage_late_init(); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 45bcfce..451b1da 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -19,8 +19,12 @@ extern void *omap3_secure_ram_storage; extern void omap3_pm_off_mode_enable(int); extern void omap_sram_idle(void); extern int omap3_can_sleep(void); +extern int omap4_can_sleep(void); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap3_idle_init(void); +extern int omap4_idle_init(void); +extern void omap4_enter_sleep(unsigned int cpu, unsigned int power_state); +extern void omap4_trigger_ioctrl(void); #if defined(CONFIG_PM_OPP) extern int omap3_opp_init(void); @@ -125,16 +129,56 @@ static inline int omap_devinit_smartreflex(void) static inline void omap_enable_smartreflex_on_init(void) {} #endif +/** + * struct omap_pmic_map - Describe the OMAP PMIC data for OMAP + * @name: name of the voltage domain + * @pmic_data: pmic data associated with it + * @omap_chip: initialize with OMAP_CHIP_INIT the OMAP chips this data maps to + * @special_action: callback for any specific action to take for that map + * + * Since we support multiple PMICs each potentially functioning on multiple + * OMAP devices, we describe the parameters in a map allowing us to reuse the + * data as necessary. + */ +struct omap_pmic_map { + char *name; + struct omap_voltdm_pmic *pmic_data; + struct omap_chip_id omap_chip; + int (*special_action)(struct voltagedomain *); +}; + +#ifdef CONFIG_PM +extern int omap_pmic_register_data(struct omap_pmic_map *map); +#else +static inline int omap_pmic_register_data(struct omap_pmic_map *map) +{ + return -EINVAL; +} +#endif +extern void omap_pmic_data_init(void); + #ifdef CONFIG_TWL4030_CORE -extern int omap3_twl_init(void); -extern int omap4_twl_init(void); +extern int omap_twl_init(void); extern int omap3_twl_set_sr_bit(bool enable); #else -static inline int omap3_twl_init(void) +static inline int omap_twl_init(void) +{ + return -EINVAL; +} +#endif + +#ifdef CONFIG_OMAP_TPS6236X +extern int omap_tps6236x_board_setup(bool use_62361, int gpio_vsel0, + int gpio_vsel1, int pull0, int pull1); +extern int omap_tps6236x_init(void); + +#else +static inline int omap_tps6236x_board_setup(bool use_62361, int gpio_vsel0, + int gpio_vsel1, int pull0, int pull1) { return -EINVAL; } -static inline int omap4_twl_init(void) +static inline int omap_tps6236x_init(void) { return -EINVAL; } diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 59a870b..40d8779 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -1,8 +1,9 @@ /* * OMAP4 Power Management Routines * - * Copyright (C) 2010 Texas Instruments, Inc. + * Copyright (C) 2010-2011 Texas Instruments, Inc. * Rajendra Nayak <rnayak@ti.com> + * Santosh Shilimkar <santosh.shilimkar@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 @@ -12,12 +13,31 @@ #include <linux/pm.h> #include <linux/suspend.h> #include <linux/module.h> +#include <linux/clk.h> #include <linux/list.h> #include <linux/err.h> #include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/delay.h> -#include "powerdomain.h" #include <mach/omap4-common.h> +#include <plat/common.h> + +#include "powerdomain.h" +#include "clockdomain.h" +#include "pm.h" +#include "prm-regbits-44xx.h" +#include "prcm44xx.h" +#include "prm44xx.h" +#include "prminst44xx.h" + +#include "clock.h" +#include "cm2_44xx.h" +#include "cm1_44xx.h" +#include "cm-regbits-44xx.h" +#include "cminst44xx.h" + struct power_state { struct powerdomain *pwrdm; @@ -29,11 +49,129 @@ struct power_state { }; static LIST_HEAD(pwrst_list); +static struct powerdomain *mpu_pwrdm, *cpu0_pwrdm; +static struct powerdomain *core_pwrdm, *per_pwrdm; + +#define MAX_IOPAD_LATCH_TIME 1000 +void omap4_trigger_ioctrl(void) +{ + int i = 0; + + /* Trigger WUCLKIN enable */ + omap4_prminst_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, OMAP4430_WUCLK_CTRL_MASK, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET); + omap_test_timeout( + ((omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET) + >> OMAP4430_WUCLK_STATUS_SHIFT) == 1), + MAX_IOPAD_LATCH_TIME, i); + /* Trigger WUCLKIN disable */ + omap4_prminst_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET); + return; +} #ifdef CONFIG_SUSPEND +/* This is a common low power function called from suspend and + * cpuidle + */ +void omap4_enter_sleep(unsigned int cpu, unsigned int power_state) +{ + int cpu0_next_state = PWRDM_POWER_ON; + int per_next_state = PWRDM_POWER_ON; + int core_next_state = PWRDM_POWER_ON; + + pwrdm_clear_all_prev_pwrst(cpu0_pwrdm); + pwrdm_clear_all_prev_pwrst(mpu_pwrdm); + pwrdm_clear_all_prev_pwrst(core_pwrdm); + pwrdm_clear_all_prev_pwrst(per_pwrdm); + + cpu0_next_state = pwrdm_read_next_pwrst(cpu0_pwrdm); + per_next_state = pwrdm_read_next_pwrst(per_pwrdm); + core_next_state = pwrdm_read_next_pwrst(core_pwrdm); + + if (core_next_state < PWRDM_POWER_ON) { + omap_uart_prepare_idle(0); + omap_uart_prepare_idle(1); + omap_uart_prepare_idle(2); + omap_uart_prepare_idle(3); + omap2_gpio_prepare_for_idle(0); + omap4_trigger_ioctrl(); + } + + omap4_enter_lowpower(cpu, power_state); + + if (core_next_state < PWRDM_POWER_ON) { + omap2_gpio_resume_after_idle(); + omap_uart_resume_idle(0); + omap_uart_resume_idle(1); + omap_uart_resume_idle(2); + omap_uart_resume_idle(3); + } + + return; +} + static int omap4_pm_suspend(void) { - do_wfi(); + struct power_state *pwrst; + int state, ret = 0; + + /* Wakeup timer from suspend */ + if (wakeup_timer_seconds || wakeup_timer_milliseconds) + omap2_pm_wakeup_on_timer(wakeup_timer_seconds, + wakeup_timer_milliseconds); + + /* Save current powerdomain state */ + list_for_each_entry(pwrst, &pwrst_list, node) { + pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm); + } + + /* Set targeted power domain states by suspend */ + list_for_each_entry(pwrst, &pwrst_list, node) { +#ifdef CONFIG_OMAP_ALLOW_OSWR + if ((!strcmp(pwrst->pwrdm->name, "cpu0_pwrdm")) || + (!strcmp(pwrst->pwrdm->name, "cpu1_pwrdm"))) + continue; + + /*OSWR is supported on silicon > ES2.0 */ + if ((pwrst->pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) + && (omap_rev() >= OMAP4430_REV_ES2_1)) + pwrdm_set_logic_retst(pwrst->pwrdm, + PWRDM_POWER_OFF); +#endif + pwrst->next_state = PWRDM_POWER_RET; + omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); + } + + /* + * For MPUSS to hit power domain retention(CSWR or OSWR), + * CPU0 and CPU1 power domain needs to be in OFF or DORMANT + * state. For MPUSS to reach off-mode. CPU0 and CPU1 power domain + * should be in off state. + * Only master CPU followes suspend path. All other CPUs follow + * cpu-hotplug path in system wide suspend. On OMAP4, CPU power + * domain CSWR is not supported by hardware. + * More details can be found in OMAP4430 TRM section 4.3.4.2. + */ + omap_uart_prepare_suspend(); + omap4_enter_sleep(0, PWRDM_POWER_OFF); + + /* Restore next powerdomain state */ + list_for_each_entry(pwrst, &pwrst_list, node) { + state = pwrdm_read_prev_pwrst(pwrst->pwrdm); + if (state > pwrst->next_state) { + pr_info("Powerdomain (%s) didn't enter " + "target state %d\n", + pwrst->pwrdm->name, pwrst->next_state); + ret = -1; + } + omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); + } + if (ret) + pr_err("Could not enter target state in pm_suspend\n"); + else + pr_err("Successfully put all powerdomains to target state\n"); + return 0; } @@ -71,8 +209,26 @@ static const struct platform_suspend_ops omap_pm_ops = { .enter = omap4_pm_enter, .valid = suspend_valid_only_mem, }; +#else +void omap4_enter_sleep(unsigned int cpu, unsigned int power_state){ return; } #endif /* CONFIG_SUSPEND */ +/* + * Enable hardware supervised mode for all clockdomains if it's + * supported. Initiate sleep transition for other clockdomains, if + * they are not used + */ +static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) +{ + if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) + clkdm_allow_idle(clkdm); + else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && + atomic_read(&clkdm->usecount) == 0) + clkdm_sleep(clkdm); + return 0; +} + + static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) { struct power_state *pwrst; @@ -83,11 +239,87 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC); if (!pwrst) return -ENOMEM; + pwrst->pwrdm = pwrdm; - pwrst->next_state = PWRDM_POWER_ON; + if ((!strcmp(pwrdm->name, "mpu_pwrdm")) || + (!strcmp(pwrdm->name, "core_pwrdm")) || + (!strcmp(pwrdm->name, "cpu0_pwrdm")) || + (!strcmp(pwrdm->name, "cpu1_pwrdm"))) + pwrst->next_state = PWRDM_POWER_ON; + else + pwrst->next_state = PWRDM_POWER_RET; list_add(&pwrst->node, &pwrst_list); - return pwrdm_set_next_pwrst(pwrst->pwrdm, pwrst->next_state); + return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); +} + +static void __init prcm_setup_regs(void) +{ + /* Enable IO_ST interrupt */ + omap4_prminst_rmw_inst_reg_bits(OMAP4430_IO_ST_MASK, OMAP4430_IO_ST_MASK, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQENABLE_MPU_OFFSET); + + /* Enable GLOBAL_WUEN */ + omap4_prminst_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK, OMAP4430_GLOBAL_WUEN_MASK, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET); + /* + * Errata ID: i608 Impacted OMAP4430 ES 1.0,2.0,2.1,2.2 + * On OMAP4, Retention-Till-Access Memory feature is not working + * reliably and hardware recommondation is keep it disabled by + * default + */ + omap4_prminst_rmw_inst_reg_bits(OMAP4430_DISABLE_RTA_EXPORT_MASK, + 0x1 << OMAP4430_DISABLE_RTA_EXPORT_SHIFT, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_SRAM_WKUP_SETUP_OFFSET); + omap4_prminst_rmw_inst_reg_bits(OMAP4430_DISABLE_RTA_EXPORT_MASK, + 0x1 << OMAP4430_DISABLE_RTA_EXPORT_SHIFT, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_LDO_SRAM_CORE_SETUP_OFFSET); + omap4_prminst_rmw_inst_reg_bits(OMAP4430_DISABLE_RTA_EXPORT_MASK, + 0x1 << OMAP4430_DISABLE_RTA_EXPORT_SHIFT, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_LDO_SRAM_MPU_SETUP_OFFSET); + omap4_prminst_rmw_inst_reg_bits(OMAP4430_DISABLE_RTA_EXPORT_MASK, + 0x1 << OMAP4430_DISABLE_RTA_EXPORT_SHIFT, + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_LDO_SRAM_IVA_SETUP_OFFSET); + /* Toggle CLKREQ in RET and OFF states */ + omap4_prminst_write_inst_reg(0x2, OMAP4430_PRM_PARTITION, + OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_CLKREQCTRL_OFFSET); + /* + * De-assert PWRREQ signal in Device OFF state + * 0x3: PWRREQ is de-asserted if all voltage domain are in + * OFF state. Conversely, PWRREQ is asserted upon any + * voltage domain entering or staying in ON or SLEEP or + * RET state. + */ + omap4_prminst_write_inst_reg(0x3, OMAP4430_PRM_PARTITION, + OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_PWRREQCTRL_OFFSET); +} +static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) +{ + u32 irqenable_mpu, irqstatus_mpu; + + irqenable_mpu = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, + OMAP4_PRM_IRQENABLE_MPU_OFFSET); + irqstatus_mpu = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, + OMAP4_PRM_IRQSTATUS_MPU_OFFSET); + + /* Check if a IO_ST interrupt */ + if (irqstatus_mpu & OMAP4430_IO_ST_MASK) { + omap4_trigger_ioctrl(); + } + + /* Clear the interrupt */ + irqstatus_mpu &= irqenable_mpu; + omap4_prm_write_inst_reg(irqstatus_mpu, OMAP4430_PRM_OCP_SOCKET_INST, + OMAP4_PRM_IRQSTATUS_MPU_OFFSET); + + return IRQ_HANDLED; +} + +int omap4_can_sleep(void) +{ + if (!omap_uart_can_sleep()) + return -1; + return 0; } /** @@ -99,22 +331,83 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) static int __init omap4_pm_init(void) { int ret; + struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm; + struct clockdomain *ducati_clkdm, *l3_2_clkdm; if (!cpu_is_omap44xx()) return -ENODEV; + if (omap_rev() == OMAP4430_REV_ES1_0) { + WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); + return -ENODEV; + } + pr_err("Power Management for TI OMAP4.\n"); + prcm_setup_regs(); + + ret = request_irq(OMAP44XX_IRQ_PRCM, + (irq_handler_t)prcm_interrupt_handler, + IRQF_DISABLED, "prcm", NULL); + if (ret) { + printk(KERN_ERR "request_irq failed to register for 0x%x\n", + OMAP44XX_IRQ_PRCM); + goto err2; + } ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { pr_err("Failed to setup powerdomains\n"); goto err2; } + /* + * The dynamic dependency between MPUSS -> MEMIF and + * MPUSS -> L3_* and DUCATI -> doesn't work as expected. + * The hardware recommendation is to keep above dependencies. + * Without this system locks up or randomly crashesh. + */ + mpuss_clkdm = clkdm_lookup("mpuss_clkdm"); + emif_clkdm = clkdm_lookup("l3_emif_clkdm"); + l3_1_clkdm = clkdm_lookup("l3_1_clkdm"); + l3_2_clkdm = clkdm_lookup("l3_2_clkdm"); + ducati_clkdm = clkdm_lookup("ducati_clkdm"); + if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || + (!l3_2_clkdm) || (!ducati_clkdm)) + goto err2; + + ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm); + ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm); + ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm); + ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm); + ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm); + if (ret) { + pr_err("Failed to add MPUSS -> L3/EMIF, DUCATI -> L3" + "wakeup dependency\n"); + goto err2; + } + + (void) clkdm_for_each(clkdms_setup, NULL); + + pr_info("OMAP4 PM: Temporary static dependency added between" + "MPUSS <-> EMIF and MPUSS <-> L3_MAIN_1.\n"); + + ret = omap4_mpuss_init(); + if (ret) { + pr_err("Failed to initialise OMAP4 MPUSS\n"); + goto err2; + } + #ifdef CONFIG_SUSPEND suspend_set_ops(&omap_pm_ops); #endif /* CONFIG_SUSPEND */ + mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); + cpu0_pwrdm = pwrdm_lookup("cpu0_pwrdm"); + core_pwrdm = pwrdm_lookup("core_pwrdm"); + per_pwrdm = pwrdm_lookup("l4per_pwrdm"); + + omap4_idle_init(); + err2: return ret; } diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 9d53a34..71d9b75 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -19,6 +19,8 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/string.h> +#include <linux/slab.h> + #include <trace/events/power.h> #include "cm2xxx_3xxx.h" @@ -77,6 +79,7 @@ static struct powerdomain *_pwrdm_lookup(const char *name) static int _pwrdm_register(struct powerdomain *pwrdm) { int i; + struct voltagedomain *voltdm; if (!pwrdm || !pwrdm->name) return -EINVAL; @@ -94,6 +97,16 @@ static int _pwrdm_register(struct powerdomain *pwrdm) if (_pwrdm_lookup(pwrdm->name)) return -EEXIST; + voltdm = voltdm_lookup(pwrdm->voltdm.name); + if (!voltdm) { + pr_err("powerdomain: %s: voltagedomain %s does not exist\n", + pwrdm->name, pwrdm->voltdm.name); + return -EINVAL; + } + pwrdm->voltdm.ptr = voltdm; + INIT_LIST_HEAD(&pwrdm->voltdm_node); + voltdm_add_pwrdm(voltdm, pwrdm); + list_add(&pwrdm->node, &pwrdm_list); /* Initialize the powerdomain's state counter */ @@ -108,6 +121,13 @@ static int _pwrdm_register(struct powerdomain *pwrdm) pwrdm->state = pwrdm_read_pwrst(pwrdm); pwrdm->state_counter[pwrdm->state] = 1; + /* Initialize priority ordered list for wakeup latency constraint */ + spin_lock_init(&pwrdm->wakeuplat_lock); + plist_head_init(&pwrdm->wakeuplat_dev_list, &pwrdm->wakeuplat_lock); + + /* res_mutex protects res_list add and del ops */ + mutex_init(&pwrdm->wakeuplat_mutex); + pr_debug("powerdomain: registered %s\n", pwrdm->name); return 0; @@ -208,6 +228,7 @@ void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs) { struct powerdomain **p = NULL; + if (!custom_funcs) WARN(1, "powerdomain: No custom pwrdm functions registered\n"); else @@ -383,6 +404,18 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, } /** + * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in + * @pwrdm: struct powerdomain * + * + * Return a pointer to the struct voltageomain that the specified powerdomain + * @pwrdm exists in. + */ +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm) +{ + return pwrdm->voltdm.ptr; +} + +/** * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain * @pwrdm: struct powerdomain * * @@ -1005,3 +1038,163 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) return 0; } + + +/** + * pwrdm_wakeuplat_set_constraint - Set powerdomain wakeup latency constraint + * @pwrdm: struct powerdomain * to which requesting device belongs to + * @dev: struct device * of requesting device + * @t: wakeup latency constraint in microseconds + * + * Adds new entry to powerdomain's wakeup latency constraint list. + * If the requesting device already exists in the list, old value is + * overwritten. Checks whether current power state is still adequate. + * Returns -EINVAL if the powerdomain or device pointer is NULL, + * or -ENOMEM if kmalloc fails, or -ERANGE if constraint can't be met, + * or returns 0 upon success. + */ +int pwrdm_wakeuplat_set_constraint (struct powerdomain *pwrdm, + struct device *dev, unsigned long t) +{ + struct wakeuplat_dev_list *user; + int found = 0, ret = 0; + + if (!pwrdm || !dev) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + } + + mutex_lock(&pwrdm->wakeuplat_mutex); + + plist_for_each_entry(user, &pwrdm->wakeuplat_dev_list, node) { + if (user->dev == dev) { + found = 1; + break; + } + } + + /* Add new entry to the list or update existing request */ + if (found && user->constraint_us == t) { + goto exit_set; + } else if (!found) { + user = kzalloc(sizeof(struct wakeuplat_dev_list), GFP_KERNEL); + if (!user) { + pr_err("OMAP PM: FATAL ERROR: kzalloc failed\n"); + ret = -ENOMEM; + goto exit_set; + } + user->dev = dev; + } else { + plist_del(&user->node, &pwrdm->wakeuplat_dev_list); + } + + plist_node_init(&user->node, t); + plist_add(&user->node, &pwrdm->wakeuplat_dev_list); + user->node.prio = user->constraint_us = t; + + ret = pwrdm_wakeuplat_update_pwrst(pwrdm); + +exit_set: + mutex_unlock(&pwrdm->wakeuplat_mutex); + + return ret; +} + +/** + * pwrdm_wakeuplat_release_constraint - Release powerdomain wkuplat constraint + * @pwrdm: struct powerdomain * to which requesting device belongs to + * @dev: struct device * of requesting device + * + * Removes device's entry from powerdomain's wakeup latency constraint list. + * Checks whether current power state is still adequate. + * Returns -EINVAL if the powerdomain or device pointer is NULL or + * no such entry exists in the list, or returns 0 upon success. + */ +int pwrdm_wakeuplat_release_constraint (struct powerdomain *pwrdm, + struct device *dev) +{ + struct wakeuplat_dev_list *user; + int found = 0, ret = 0; + + if (!pwrdm || !dev) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + } + + mutex_lock(&pwrdm->wakeuplat_mutex); + + plist_for_each_entry(user, &pwrdm->wakeuplat_dev_list, node) { + if (user->dev == dev) { + found = 1; + break; + } + } + + if (!found) { + pr_err("OMAP PM: Error: no prior constraint to release\n"); + ret = -EINVAL; + goto exit_rls; + } + + plist_del(&user->node, &pwrdm->wakeuplat_dev_list); + kfree(user); + + ret = pwrdm_wakeuplat_update_pwrst(pwrdm); + +exit_rls: + mutex_unlock(&pwrdm->wakeuplat_mutex); + + return ret; +} + +/** + * pwrdm_wakeuplat_update_pwrst - Update power domain power state if needed + * @pwrdm: struct powerdomain * to which requesting device belongs to + * + * Finds minimum latency value from all entries in the list and + * the power domain power state neeting the constraint. Programs + * new state if it is different from current power state. + * Returns -EINVAL if the powerdomain or device pointer is NULL or + * no such entry exists in the list, or -ERANGE if constraint can't be met, + * or returns 0 upon success. + */ +int pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm) +{ + struct plist_node *node; + int ret = 0, new_state; + unsigned long min_latency = -1; + + if (!plist_head_empty(&pwrdm->wakeuplat_dev_list)) { + node = plist_last(&pwrdm->wakeuplat_dev_list); + min_latency = node->prio; + } + + /* Find power state with wakeup latency < minimum constraint. */ + for (new_state = 0x0; new_state < PWRDM_MAX_PWRSTS; new_state++) { + if (min_latency == -1 || + pwrdm->wakeup_lat[new_state] < min_latency) + break; + } + + /* No power state wkuplat met constraint. Keep power domain ON. */ + if (new_state == PWRDM_MAX_PWRSTS) { + new_state = PWRDM_FUNC_PWRST_ON; + ret = -ERANGE; + } + + /* OSWR is not supported, set CSWR instead. TODO: add OSWR support */ + if (new_state == PWRDM_FUNC_PWRST_OSWR) + new_state = PWRDM_FUNC_PWRST_CSWR; + + if (pwrdm->state != new_state) { + if (cpu_is_omap44xx() || cpu_is_omap34xx()) + omap_set_pwrdm_state(pwrdm, new_state); + } + + pr_debug("OMAP PM: %s pwrst: curr= %d, prev= %d next= %d " + "wkuplat_min= %lu, state= %d\n", pwrdm->name, + pwrdm_read_pwrst(pwrdm), pwrdm_read_prev_pwrst(pwrdm), + pwrdm_read_next_pwrst(pwrdm), min_latency, new_state); + + return ret; +} diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 012827f..12108f7 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -19,11 +19,16 @@ #include <linux/types.h> #include <linux/list.h> +#include <linux/plist.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> #include <linux/atomic.h> #include <plat/cpu.h> +#include "voltage.h" + /* Powerdomain basic power states */ #define PWRDM_POWER_OFF 0x0 #define PWRDM_POWER_RET 0x1 @@ -43,6 +48,18 @@ #define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON) #define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON) +#define PWRSTS_RET_INA_ON ((1 << PWRDM_POWER_RET) | \ + (1 << PWRDM_POWER_INACTIVE) | \ + (1 << PWRDM_POWER_ON)) + +#define PWRSTS_OFF_INA_ON ((1 << PWRDM_POWER_OFF) | \ + (1 << PWRDM_POWER_INACTIVE) | \ + (1 << PWRDM_POWER_ON)) + +#define PWRSTS_OFF_RET_INA_ON ((1 << PWRDM_POWER_OFF) | \ + (1 << PWRDM_POWER_RET) | \ + (1 << PWRDM_POWER_INACTIVE) | \ + (1 << PWRDM_POWER_ON)) /* Powerdomain flags */ #define PWRDM_HAS_HDWR_SAR (1 << 0) /* hardware save-and-restore support */ @@ -72,12 +89,23 @@ /* XXX A completely arbitrary number. What is reasonable here? */ #define PWRDM_TRANSITION_BAILOUT 100000 +/* Powerdomain functional power states */ +#define PWRDM_FUNC_PWRST_OFF 0x0 +#define PWRDM_FUNC_PWRST_OSWR 0x1 +#define PWRDM_FUNC_PWRST_CSWR 0x2 +#define PWRDM_FUNC_PWRST_ON 0x3 + +#define PWRDM_MAX_FUNC_PWRSTS 4 + +#define UNSUP_STATE -1 + struct clockdomain; struct powerdomain; /** * struct powerdomain - OMAP powerdomain * @name: Powerdomain name + * @voltdm: voltagedomain containing this powerdomain * @omap_chip: represents the OMAP chip types containing this pwrdm * @prcm_offs: the address offset from CM_BASE/PRM_BASE * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs @@ -89,15 +117,22 @@ struct powerdomain; * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON * @pwrdm_clkdms: Clockdomains in this powerdomain * @node: list_head linking all powerdomains + * @voltdm_node: list_head linking all powerdomains in a voltagedomain * @state: * @state_counter: * @timer: * @state_timer: - * - * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h. + * @wakeup_lat: Wakeup latencies for possible powerdomain power states + * @wakeuplat_lock: spinlock for plist + * @wakeuplat_dev_list: plist_head linking all devices placing constraint + * @wa * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h. */ struct powerdomain { const char *name; + union { + const char *name; + struct voltagedomain *ptr; + } voltdm; const struct omap_chip_id omap_chip; const s16 prcm_offs; const u8 pwrsts; @@ -109,6 +144,7 @@ struct powerdomain { const u8 prcm_partition; struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; struct list_head node; + struct list_head voltdm_node; int state; unsigned state_counter[PWRDM_MAX_PWRSTS]; unsigned ret_logic_off_counter; @@ -118,6 +154,16 @@ struct powerdomain { s64 timer; s64 state_timer[PWRDM_MAX_PWRSTS]; #endif + const u32 wakeup_lat[PWRDM_MAX_FUNC_PWRSTS]; + spinlock_t wakeuplat_lock; + struct plist_head wakeuplat_dev_list; + struct mutex wakeuplat_mutex; +}; + +struct wakeuplat_dev_list { + struct device *dev; + unsigned long constraint_us; + struct plist_node node; }; /** @@ -176,6 +222,7 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, int (*fn)(struct powerdomain *pwrdm, struct clockdomain *clkdm)); +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm); int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); @@ -226,5 +273,10 @@ extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank); extern struct powerdomain wkup_omap2_pwrdm; extern struct powerdomain gfx_omap2_pwrdm; +int pwrdm_wakeuplat_set_constraint(struct powerdomain *pwrdm, + struct device *dev, unsigned long t); +int pwrdm_wakeuplat_release_constraint(struct powerdomain *pwrdm, + struct device *dev); +int pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm); #endif diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c index 4210c33..2242c8e 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c @@ -70,6 +70,7 @@ struct powerdomain gfx_omap2_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, }; struct powerdomain wkup_omap2_pwrdm = { @@ -77,4 +78,5 @@ struct powerdomain wkup_omap2_pwrdm = { .prcm_offs = WKUP_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), .pwrsts = PWRSTS_ON, + .voltdm = { .name = "wakeup" }, }; diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c index cc389fb..274f64c 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c @@ -38,6 +38,7 @@ static struct powerdomain dsp_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, }, + .voltdm = { .name = "core" }, }; static struct powerdomain mpu_24xx_pwrdm = { @@ -53,6 +54,7 @@ static struct powerdomain mpu_24xx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, }, + .voltdm = { .name = "core" }, }; static struct powerdomain core_24xx_pwrdm = { @@ -71,6 +73,7 @@ static struct powerdomain core_24xx_pwrdm = { [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */ }, + .voltdm = { .name = "core" }, }; @@ -95,6 +98,7 @@ static struct powerdomain mdm_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, }; #endif /* CONFIG_SOC_OMAP2430 */ diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c index 469a920..b91224b 100644 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c @@ -52,6 +52,13 @@ static struct powerdomain iva2_pwrdm = { [2] = PWRSTS_OFF_ON, [3] = PWRSTS_ON, }, + .voltdm = { .name = "mpu_iva" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1100, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 350, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain mpu_3xxx_pwrdm = { @@ -68,6 +75,13 @@ static struct powerdomain mpu_3xxx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_OFF_ON, }, + .voltdm = { .name = "mpu_iva" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 95, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 45, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* @@ -98,6 +112,13 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = { [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 100, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 60, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain core_3xxx_es3_1_pwrdm = { @@ -121,6 +142,13 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = { [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 100, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 60, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain dss_pwrdm = { @@ -136,6 +164,13 @@ static struct powerdomain dss_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 70, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 20, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* @@ -157,6 +192,13 @@ static struct powerdomain sgx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain cam_pwrdm = { @@ -172,6 +214,13 @@ static struct powerdomain cam_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 850, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 35, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain per_pwrdm = { @@ -187,12 +236,20 @@ static struct powerdomain per_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 200, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 110, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain emu_pwrdm = { .name = "emu_pwrdm", .prcm_offs = OMAP3430_EMU_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .voltdm = { .name = "core" }, }; static struct powerdomain neon_pwrdm = { @@ -201,6 +258,13 @@ static struct powerdomain neon_pwrdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), .pwrsts = PWRSTS_OFF_RET_ON, .pwrsts_logic_ret = PWRSTS_RET, + .voltdm = { .name = "mpu_iva" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 200, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 35, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain usbhost_pwrdm = { @@ -223,36 +287,48 @@ static struct powerdomain usbhost_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, + .voltdm = { .name = "core" }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 800, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 150, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; static struct powerdomain dpll1_pwrdm = { .name = "dpll1_pwrdm", .prcm_offs = MPU_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain dpll2_pwrdm = { .name = "dpll2_pwrdm", .prcm_offs = OMAP3430_IVA2_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain dpll3_pwrdm = { .name = "dpll3_pwrdm", .prcm_offs = PLL_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .voltdm = { .name = "core" }, }; static struct powerdomain dpll4_pwrdm = { .name = "dpll4_pwrdm", .prcm_offs = PLL_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .voltdm = { .name = "core" }, }; static struct powerdomain dpll5_pwrdm = { .name = "dpll5_pwrdm", .prcm_offs = PLL_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), + .voltdm = { .name = "core" }, }; /* As powerdomains are added or removed above, this list must also be changed */ diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c index c4222c7..ec24a39 100644 --- a/arch/arm/mach-omap2/powerdomains44xx_data.c +++ b/arch/arm/mach-omap2/powerdomains44xx_data.c @@ -1,7 +1,7 @@ /* * OMAP4 Power domains framework * - * Copyright (C) 2009-2010 Texas Instruments, Inc. + * Copyright (C) 2009-2011 Texas Instruments, Inc. * Copyright (C) 2009-2011 Nokia Corporation * * Abhijit Pagare (abhijitpagare@ti.com) @@ -33,10 +33,11 @@ /* core_44xx_pwrdm: CORE power domain */ static struct powerdomain core_44xx_pwrdm = { .name = "core_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_CORE_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 5, .pwrsts_mem_ret = { @@ -54,15 +55,22 @@ static struct powerdomain core_44xx_pwrdm = { [4] = PWRSTS_ON, /* ducati_unicache */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* gfx_44xx_pwrdm: 3D accelerator power domain */ static struct powerdomain gfx_44xx_pwrdm = { .name = "gfx_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_GFX_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_INA_ON, .banks = 1, .pwrsts_mem_ret = { [0] = PWRSTS_OFF, /* gfx_mem */ @@ -71,15 +79,22 @@ static struct powerdomain gfx_44xx_pwrdm = { [0] = PWRSTS_ON, /* gfx_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* abe_44xx_pwrdm: Audio back end power domain */ static struct powerdomain abe_44xx_pwrdm = { .name = "abe_pwrdm", + .voltdm = { .name = "iva" }, .prcm_offs = OMAP4430_PRM_ABE_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF, .banks = 2, .pwrsts_mem_ret = { @@ -91,15 +106,22 @@ static struct powerdomain abe_44xx_pwrdm = { [1] = PWRSTS_ON, /* periphmem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* dss_44xx_pwrdm: Display subsystem power domain */ static struct powerdomain dss_44xx_pwrdm = { .name = "dss_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_DSS_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF, .banks = 1, .pwrsts_mem_ret = { @@ -109,15 +131,22 @@ static struct powerdomain dss_44xx_pwrdm = { [0] = PWRSTS_ON, /* dss_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* tesla_44xx_pwrdm: Tesla processor power domain */ static struct powerdomain tesla_44xx_pwrdm = { .name = "tesla_pwrdm", + .voltdm = { .name = "iva" }, .prcm_offs = OMAP4430_PRM_TESLA_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 3, .pwrsts_mem_ret = { @@ -131,14 +160,21 @@ static struct powerdomain tesla_44xx_pwrdm = { [2] = PWRSTS_ON, /* tesla_l2 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* wkup_44xx_pwrdm: Wake-up power domain */ static struct powerdomain wkup_44xx_pwrdm = { .name = "wkup_pwrdm", + .voltdm = { .name = "wakeup" }, .prcm_offs = OMAP4430_PRM_WKUP_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), .pwrsts = PWRSTS_ON, .banks = 1, .pwrsts_mem_ret = { @@ -152,10 +188,11 @@ static struct powerdomain wkup_44xx_pwrdm = { /* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */ static struct powerdomain cpu0_44xx_pwrdm = { .name = "cpu0_pwrdm", + .voltdm = { .name = "mpu" }, .prcm_offs = OMAP4430_PRCM_MPU_CPU0_INST, .prcm_partition = OMAP4430_PRCM_MPU_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 1, .pwrsts_mem_ret = { @@ -164,15 +201,22 @@ static struct powerdomain cpu0_44xx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* cpu0_l1 */ }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */ static struct powerdomain cpu1_44xx_pwrdm = { .name = "cpu1_pwrdm", + .voltdm = { .name = "mpu" }, .prcm_offs = OMAP4430_PRCM_MPU_CPU1_INST, .prcm_partition = OMAP4430_PRCM_MPU_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 1, .pwrsts_mem_ret = { @@ -181,14 +225,21 @@ static struct powerdomain cpu1_44xx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* cpu1_l1 */ }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* emu_44xx_pwrdm: Emulation power domain */ static struct powerdomain emu_44xx_pwrdm = { .name = "emu_pwrdm", + .voltdm = { .name = "wakeup" }, .prcm_offs = OMAP4430_PRM_EMU_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), .pwrsts = PWRSTS_OFF_ON, .banks = 1, .pwrsts_mem_ret = { @@ -200,12 +251,13 @@ static struct powerdomain emu_44xx_pwrdm = { }; /* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */ -static struct powerdomain mpu_44xx_pwrdm = { +static struct powerdomain mpu_443x_pwrdm = { .name = "mpu_pwrdm", + .voltdm = { .name = "mpu" }, .prcm_offs = OMAP4430_PRM_MPU_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP443X), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 3, .pwrsts_mem_ret = { @@ -218,15 +270,47 @@ static struct powerdomain mpu_44xx_pwrdm = { [1] = PWRSTS_ON, /* mpu_l2 */ [2] = PWRSTS_ON, /* mpu_ram */ }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, +}; + +static struct powerdomain mpu_446x_pwrdm = { + .name = "mpu_pwrdm", + .voltdm = { .name = "mpu" }, + .prcm_offs = OMAP4430_PRM_MPU_INST, + .prcm_partition = OMAP4430_PRM_PARTITION, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), + .pwrsts = PWRSTS_RET_INA_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .banks = 2, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, /* mpu_l2 */ + [1] = PWRSTS_RET, /* mpu_ram */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_ON, /* mpu_l2 */ + [1] = PWRSTS_ON, /* mpu_ram */ + }, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* ivahd_44xx_pwrdm: IVA-HD power domain */ static struct powerdomain ivahd_44xx_pwrdm = { .name = "ivahd_pwrdm", + .voltdm = { .name = "iva" }, .prcm_offs = OMAP4430_PRM_IVAHD_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF, .banks = 4, .pwrsts_mem_ret = { @@ -242,15 +326,22 @@ static struct powerdomain ivahd_44xx_pwrdm = { [3] = PWRSTS_ON, /* tcm2_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* cam_44xx_pwrdm: Camera subsystem power domain */ static struct powerdomain cam_44xx_pwrdm = { .name = "cam_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_CAM_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_INA_ON, .banks = 1, .pwrsts_mem_ret = { [0] = PWRSTS_OFF, /* cam_mem */ @@ -259,15 +350,22 @@ static struct powerdomain cam_44xx_pwrdm = { [0] = PWRSTS_ON, /* cam_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* l3init_44xx_pwrdm: L3 initators pheripherals power domain */ static struct powerdomain l3init_44xx_pwrdm = { .name = "l3init_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_L3INIT_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 1, .pwrsts_mem_ret = { @@ -277,15 +375,22 @@ static struct powerdomain l3init_44xx_pwrdm = { [0] = PWRSTS_ON, /* l3init_bank1 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = 1000, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* l4per_44xx_pwrdm: Target peripherals power domain */ static struct powerdomain l4per_44xx_pwrdm = { .name = "l4per_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_L4PER_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_RET_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 2, .pwrsts_mem_ret = { @@ -297,6 +402,12 @@ static struct powerdomain l4per_44xx_pwrdm = { [1] = PWRSTS_ON, /* retained_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, + .wakeup_lat = { + [PWRDM_FUNC_PWRST_OFF] = UNSUP_STATE, + [PWRDM_FUNC_PWRST_OSWR] = 600, + [PWRDM_FUNC_PWRST_CSWR] = 300, + [PWRDM_FUNC_PWRST_ON] = 0, + }, }; /* @@ -305,19 +416,21 @@ static struct powerdomain l4per_44xx_pwrdm = { */ static struct powerdomain always_on_core_44xx_pwrdm = { .name = "always_on_core_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_ALWAYS_ON_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), .pwrsts = PWRSTS_ON, }; /* cefuse_44xx_pwrdm: Customer efuse controller power domain */ static struct powerdomain cefuse_44xx_pwrdm = { .name = "cefuse_pwrdm", + .voltdm = { .name = "core" }, .prcm_offs = OMAP4430_PRM_CEFUSE_INST, .prcm_partition = OMAP4430_PRM_PARTITION, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), - .pwrsts = PWRSTS_OFF_ON, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), + .pwrsts = PWRSTS_OFF_INA_ON, }; /* @@ -339,7 +452,8 @@ static struct powerdomain *powerdomains_omap44xx[] __initdata = { &cpu0_44xx_pwrdm, &cpu1_44xx_pwrdm, &emu_44xx_pwrdm, - &mpu_44xx_pwrdm, + &mpu_443x_pwrdm, + &mpu_446x_pwrdm, &ivahd_44xx_pwrdm, &cam_44xx_pwrdm, &l3init_44xx_pwrdm, diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h index 6d2776f..175412a 100644 --- a/arch/arm/mach-omap2/prm-regbits-44xx.h +++ b/arch/arm/mach-omap2/prm-regbits-44xx.h @@ -1,7 +1,7 @@ /* * OMAP44xx Power Management register bits * - * Copyright (C) 2009-2010 Texas Instruments, Inc. + * Copyright (C) 2009-2011 Texas Instruments, Inc. * Copyright (C) 2009-2010 Nokia Corporation * * Paul Walmsley (paul@pwsan.com) @@ -283,6 +283,14 @@ #define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT 10 #define OMAP4430_DUCATI_UNICACHE_STATEST_MASK (0x3 << 10) +/* Used by PRM_DEVICE_OFF_CTRL */ +#define OMAP4460_EMIF1_OFFWKUP_DISABLE_SHIFT 8 +#define OMAP4460_EMIF1_OFFWKUP_DISABLE_MASK (1 << 8) + +/* Used by PRM_DEVICE_OFF_CTRL */ +#define OMAP4460_EMIF2_OFFWKUP_DISABLE_SHIFT 9 +#define OMAP4460_EMIF2_OFFWKUP_DISABLE_MASK (1 << 9) + /* Used by RM_MPU_RSTST */ #define OMAP4430_EMULATION_RST_SHIFT 0 #define OMAP4430_EMULATION_RST_MASK (1 << 0) @@ -1063,6 +1071,14 @@ #define OMAP4430_SCLL_SHIFT 8 #define OMAP4430_SCLL_MASK (0xff << 8) +/* Used by PRM_VC_CFG_I2C_CLK */ +#define OMAP4430_HSCLH_SHIFT 16 +#define OMAP4430_HSCLH_MASK (0xff << 16) + +/* Used by PRM_VC_CFG_I2C_CLK */ +#define OMAP4430_HSCLL_SHIFT 24 +#define OMAP4430_HSCLL_MASK (0xff << 24) + /* Used by PRM_RSTST */ #define OMAP4430_SECURE_WDT_RST_SHIFT 4 #define OMAP4430_SECURE_WDT_RST_MASK (1 << 4) diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 051213f..3b83763 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -20,6 +20,8 @@ #include <plat/cpu.h> #include <plat/prcm.h> +#include "vp.h" + #include "prm2xxx_3xxx.h" #include "cm2xxx_3xxx.h" #include "prm-regbits-24xx.h" @@ -156,3 +158,57 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift) return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; } + +/* PRM VP */ + +/* + * struct omap3_vp - OMAP3 VP register access description. + * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg + */ +struct omap3_vp { + u32 tranxdone_status; +}; + +struct omap3_vp omap3_vp[] = { + [OMAP3_VP_VDD_MPU_ID] = { + .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK, + }, + [OMAP3_VP_VDD_CORE_ID] = { + .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK, + }, +}; + +#define MAX_VP_ID ARRAY_SIZE(omap3_vp); + +u32 omap3_prm_vp_check_txdone(u8 vp_id) +{ + struct omap3_vp *vp = &omap3_vp[vp_id]; + u32 irqstatus; + + irqstatus = omap2_prm_read_mod_reg(OCP_MOD, + OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + return irqstatus & vp->tranxdone_status; +} + +void omap3_prm_vp_clear_txdone(u8 vp_id) +{ + struct omap3_vp *vp = &omap3_vp[vp_id]; + + omap2_prm_write_mod_reg(vp->tranxdone_status, + OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); +} + +u32 omap3_prm_vcvp_read(u8 offset) +{ + return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset); +} + +void omap3_prm_vcvp_write(u32 val, u8 offset) +{ + omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset); +} + +u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) +{ + return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset); +} diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index a1fc62a..cef533d 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -303,7 +303,19 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift); extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); +/* OMAP3-specific VP functions */ +u32 omap3_prm_vp_check_txdone(u8 vp_id); +void omap3_prm_vp_clear_txdone(u8 vp_id); + +/* + * OMAP3 access functions for voltage controller (VC) and + * voltage proccessor (VP) in the PRM. + */ +extern u32 omap3_prm_vcvp_read(u8 offset); +extern void omap3_prm_vcvp_write(u32 val, u8 offset); +extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); #endif /* CONFIG_ARCH_OMAP4 */ + #endif /* diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index a2a04bf..8a3bba3 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -21,8 +21,11 @@ #include <plat/cpu.h> #include <plat/prcm.h> +#include "vp.h" #include "prm44xx.h" #include "prm-regbits-44xx.h" +#include "prcm44xx.h" +#include "prminst44xx.h" /* * Address offset (in bytes) between the reset control and the reset @@ -193,3 +196,71 @@ void omap4_prm_global_warm_sw_reset(void) v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, OMAP4_RM_RSTCTRL); } + +/* PRM VP */ + +/* + * struct omap4_vp - OMAP4 VP register access description. + * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP + * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg + */ +struct omap4_vp { + u32 irqstatus_mpu; + u32 tranxdone_status; +}; + +static struct omap4_vp omap4_vp[] = { + [OMAP4_VP_VDD_MPU_ID] = { + .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET, + .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK, + }, + [OMAP4_VP_VDD_IVA_ID] = { + .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, + .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK, + }, + [OMAP4_VP_VDD_CORE_ID] = { + .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, + .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK, + }, +}; + +u32 omap4_prm_vp_check_txdone(u8 vp_id) +{ + struct omap4_vp *vp = &omap4_vp[vp_id]; + u32 irqstatus; + + irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, + OMAP4430_PRM_OCP_SOCKET_INST, + vp->irqstatus_mpu); + return irqstatus & vp->tranxdone_status; +} + +void omap4_prm_vp_clear_txdone(u8 vp_id) +{ + struct omap4_vp *vp = &omap4_vp[vp_id]; + + omap4_prminst_write_inst_reg(vp->tranxdone_status, + OMAP4430_PRM_PARTITION, + OMAP4430_PRM_OCP_SOCKET_INST, + vp->irqstatus_mpu); +}; + +u32 omap4_prm_vcvp_read(u8 offset) +{ + return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, + OMAP4430_PRM_DEVICE_INST, offset); +} + +void omap4_prm_vcvp_write(u32 val, u8 offset) +{ + omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, + OMAP4430_PRM_DEVICE_INST, offset); +} + +u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) +{ + return omap4_prminst_rmw_inst_reg_bits(mask, bits, + OMAP4430_PRM_PARTITION, + OMAP4430_PRM_DEVICE_INST, + offset); +} diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h index 67a0d3f..026529f 100644 --- a/arch/arm/mach-omap2/prm44xx.h +++ b/arch/arm/mach-omap2/prm44xx.h @@ -713,8 +713,8 @@ #define OMAP4430_PRM_VC_VAL_BYPASS OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a0) #define OMAP4_PRM_VC_CFG_CHANNEL_OFFSET 0x00a4 #define OMAP4430_PRM_VC_CFG_CHANNEL OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a4) -#define OMAP4_PRM_VC_CFG_I2C_INSTE_OFFSET 0x00a8 -#define OMAP4430_PRM_VC_CFG_I2C_INSTE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8) +#define OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET 0x00a8 +#define OMAP4430_PRM_VC_CFG_I2C_MODE OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8) #define OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET 0x00ac #define OMAP4430_PRM_VC_CFG_I2C_CLK OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ac) #define OMAP4_PRM_SRAM_COUNT_OFFSET 0x00b0 @@ -773,6 +773,18 @@ extern int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift); extern void omap4_prm_global_warm_sw_reset(void); +/* OMAP4-specific VP functions */ +u32 omap4_prm_vp_check_txdone(u8 vp_id); +void omap4_prm_vp_clear_txdone(u8 vp_id); + +/* + * OMAP4 access functions for voltage controller (VC) and + * voltage proccessor (VP) in the PRM. + */ +extern u32 omap4_prm_vcvp_read(u8 offset); +extern void omap4_prm_vcvp_write(u32 val, u8 offset); +extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); + # endif #endif diff --git a/arch/arm/mach-omap2/remoteproc.c b/arch/arm/mach-omap2/remoteproc.c new file mode 100644 index 0000000..1fb3529 --- /dev/null +++ b/arch/arm/mach-omap2/remoteproc.c @@ -0,0 +1,191 @@ +/* + * Remote processor machine-specific module for OMAP4 + * + * Copyright (C) 2011 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/remoteproc.h> +#include <linux/memblock.h> + +#include <plat/omap_device.h> +#include <plat/omap_hwmod.h> +#include <plat/remoteproc.h> +#include <plat/dsp.h> +#include <plat/io.h> + +#define L4_PERIPHERAL_L4CFG (L4_44XX_BASE) +#define IPU_PERIPHERAL_L4CFG 0xAA000000 + +#define L4_PERIPHERAL_L4PER 0x48000000 +#define IPU_PERIPHERAL_L4PER 0xA8000000 + +#define L4_PERIPHERAL_L4EMU 0x54000000 +#define IPU_PERIPHERAL_L4EMU 0xB4000000 + +#define L3_IVAHD_CONFIG 0x5A000000 +#define IPU_IVAHD_CONFIG 0xBA000000 + +#define L3_IVAHD_SL2 0x5B000000 +#define IPU_IVAHD_SL2 0xBB000000 + +#define L3_TILER_MODE_0_1 0x60000000 +#define IPU_TILER_MODE_0_1 0x60000000 + +#define L3_TILER_MODE_2 0x70000000 +#define IPU_TILER_MODE_2 0x70000000 + +#define L3_TILER_MODE_3 0x78000000 +#define IPU_TILER_MODE_3 0x78000000 + +#define L3_IVAHD_CONFIG 0x5A000000 +#define IPU_IVAHD_CONFIG 0xBA000000 + +#define L3_IVAHD_SL2 0x5B000000 +#define IPU_IVAHD_SL2 0xBB000000 + +#define IPU_MEM_TEXT 0x0 +#define IPU_MEM_DATA 0x80000000 +#define IPU_MEM_IPC 0xA0000000 + +/* TODO: Remove hardcoded RAM Addresses once we have the PA->VA lookup integrated. + * IPC region should not be hard-coded. Text area is also not hard-coded since + * VA to PA translation is not required. */ +#define PHYS_MEM_DATA 0xB9800000 + +/* + * Memory mappings for the remote M3 subsystem + * + * Don't change the device addresses (first parameter), otherwise you'd have + * to update the firmware (BIOS image) accordingly. + * + * A 0 physical address (second parameter) means this physical region should + * be dynamically carved out at boot time. + */ +static struct rproc_mem_entry ipu_memory_maps[] = { + {IPU_MEM_IPC, 0, SZ_1M}, /* keep this IPC region first */ + {IPU_MEM_TEXT, 0, SZ_4M}, + {IPU_MEM_DATA, PHYS_MEM_DATA, SZ_1M * 96}, + {IPU_PERIPHERAL_L4CFG, L4_PERIPHERAL_L4CFG, SZ_16M}, + {IPU_PERIPHERAL_L4PER, L4_PERIPHERAL_L4PER, SZ_16M}, + {IPU_TILER_MODE_0_1, L3_TILER_MODE_0_1, SZ_256M}, + {IPU_TILER_MODE_2, L3_TILER_MODE_2, SZ_128M}, + {IPU_TILER_MODE_3, L3_TILER_MODE_3, SZ_128M}, + {IPU_IVAHD_CONFIG, L3_IVAHD_CONFIG, SZ_16M}, + {IPU_IVAHD_SL2, L3_IVAHD_SL2, SZ_16M}, + { } +}; + +static struct omap_rproc_pdata omap4_rproc_data[] = { + { + .name = "dsp", + .iommu_name = "tesla", + .firmware = "tesla-dsp.bin", + .oh_name = "dsp_c0", + }, + { + .name = "ipu", + .iommu_name = "ducati", + .firmware = "ducati-m3.bin", + .oh_name = "ipu_c0", + .oh_name_opt = "ipu_c1", + .memory_maps = ipu_memory_maps, + }, +}; + +static struct omap_device_pm_latency omap_rproc_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static int __init omap_rproc_init(void) +{ + const char *pdev_name = "omap-rproc"; + struct omap_hwmod *oh[2]; + struct omap_device *od; + int i, ret = 0, oh_count; + phys_addr_t paddr, size; + + /* names like ipu_cx/dsp_cx might show up on other OMAPs, too */ + if (!cpu_is_omap44xx()) + return 0; + + paddr = omap_dsp_get_mempool_base(); + size = omap_dsp_get_mempool_size(); + if (!paddr || !size) { + pr_warn("carveout memory is unavailable: 0x%x, 0x%x\n", + paddr, size); + return -ENOMEM; + } + + /* dynamically allocate carveout memory as required by the ipu */ + for (i = 0; i < ARRAY_SIZE(ipu_memory_maps); i++) { + struct rproc_mem_entry *me = &ipu_memory_maps[i]; + + if (!me->pa && me->size) { + if (me->size > size) { + pr_warn("out of carveout memory\n"); + return -ENOMEM; + } + + me->pa = paddr; + paddr += me->size; + size -= me->size; + + pr_info("0x%x bytes at 0x%x %d\n", me->size, me->pa, i); + } + } + + for (i = 0; i < ARRAY_SIZE(omap4_rproc_data); i++) { + const char *oh_name = omap4_rproc_data[i].oh_name; + const char *oh_name_opt = omap4_rproc_data[i].oh_name_opt; + oh_count = 0; + + oh[0] = omap_hwmod_lookup(oh_name); + if (!oh[0]) { + pr_err("could not look up %s\n", oh_name); + continue; + } + oh_count++; + + if (oh_name_opt) { + oh[1] = omap_hwmod_lookup(oh_name_opt); + if (!oh[1]) { + pr_err("could not look up %s\n", oh_name_opt); + continue; + } + oh_count++; + } + + od = omap_device_build_ss(pdev_name, i, oh, oh_count, + &omap4_rproc_data[i], + sizeof(struct omap_rproc_pdata), + omap_rproc_latency, + ARRAY_SIZE(omap_rproc_latency), + false); + if (IS_ERR(od)) { + pr_err("Could not build omap_device for %s:%s\n", + pdev_name, oh_name); + ret = PTR_ERR(od); + } + } + + return ret; +} +/* must be ready in time for device_initcall users */ +subsys_initcall(omap_rproc_init); diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 1ac361b..3c1564d 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -57,9 +57,9 @@ * NOTE: By default the serial timeout is disabled as it causes lost characters * over the serial ports. This means that the UART clocks will stay on until * disabled via sysfs. This also causes that any deeper omap sleep states are - * blocked. + * blocked. */ -#define DEFAULT_TIMEOUT 0 +#define DEFAULT_TIMEOUT 1000 #define MAX_UART_HWMOD_NAME_LEN 16 @@ -315,6 +315,12 @@ static void omap_uart_enable_wakeup(struct omap_uart_state *uart) v |= OMAP3_PADCONF_WAKEUPENABLE0; omap_ctrl_writew(v, uart->padconf); } + + if (cpu_is_omap44xx() && uart->padconf) { + u16 v = omap4_ctrl_pad_readw(uart->padconf); + v |= OMAP44XX_PADCONF_WAKEUPENABLE0; + omap4_ctrl_pad_writew(v, uart->padconf); + } } static void omap_uart_disable_wakeup(struct omap_uart_state *uart) @@ -347,7 +353,7 @@ static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, if (uart->dma_enabled) idlemode = HWMOD_IDLEMODE_FORCE; else - idlemode = HWMOD_IDLEMODE_SMART; + idlemode = HWMOD_IDLEMODE_SMART_WKUP; } else { idlemode = HWMOD_IDLEMODE_NO; } @@ -418,8 +424,9 @@ void omap_uart_resume_idle(int num) } /* Check for normal UART wakeup */ - if (__raw_readl(uart->wk_st) & uart->wk_mask) - omap_uart_block_sleep(uart); + if (uart->wk_st && uart->wk_mask) + if (__raw_readl(uart->wk_st) & uart->wk_mask) + omap_uart_block_sleep(uart); return; } } @@ -447,6 +454,10 @@ int omap_uart_can_sleep(void) can_sleep = 0; continue; } + if(omap_uart_active(uart->num, uart->timeout)) { + can_sleep = 0; + continue; + } /* This UART can now safely sleep. */ omap_uart_allow_sleep(uart); @@ -543,7 +554,20 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) uart->wk_en = NULL; uart->wk_st = NULL; uart->wk_mask = 0; - uart->padconf = 0; + switch (uart->num) { + case 0: + uart->padconf = 0x0E4; + break; + case 1: + uart->padconf = 0x11C; + break; + case 2: + uart->padconf = 0x144; + break; + case 3: + uart->padconf = 0x15C; + break; + } } uart->irqflags |= IRQF_SHARED; @@ -843,7 +867,8 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) console_unlock(); - if ((cpu_is_omap34xx() && uart->padconf) || + if (((cpu_is_omap34xx() || cpu_is_omap44xx()) + && uart->padconf) || (uart->wk_en && uart->wk_mask)) { device_init_wakeup(&od->pdev.dev, true); DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout); diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S new file mode 100644 index 0000000..c8ea819 --- /dev/null +++ b/arch/arm/mach-omap2/sleep44xx.S @@ -0,0 +1,486 @@ +/* + * OMAP44xx CPU low power powerdown and powerup code. + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Written by Santosh Shilimkar <santosh.shilimkar@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/linkage.h> +#include <asm/system.h> +#include <asm/smp_scu.h> +#include <asm/memory.h> +#include <asm/hardware/cache-l2x0.h> + +#include <plat/omap44xx.h> +#include <mach/omap4-common.h> + +#include "omap4-sar-layout.h" + +#ifdef CONFIG_SMP + +/* Masks used for MMU manipulation */ +#define TTRBIT_MASK 0xffffc000 +#define TABLE_INDEX_MASK 0xfff00000 +#define TABLE_ENTRY 0x00000c02 +#define CACHE_DISABLE_MASK 0xffffe7fb +#define TABLE_ADDRESS_OFFSET 0x04 +#define CR_VALUE_OFFSET 0x08 +#define SCU_POWER_SECURE_INDEX 0x108 + +/* + * ============================= + * == CPU suspend entry point == + * ============================= + * + * void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state) + * + * This function code saves the CPU context and performs the CPU + * power down sequence. Calling WFI effectively changes the CPU + * power domains states to the desired target power state. + * + * @cpu : contains cpu id (r0) + * @save_state : contains context save state (r1) + * 0 - No context lost + * 1 - CPUx L1 and logic lost: MPUSS CSWR + * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR + * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF + * @return: This function never returns for CPU OFF and DORMANT power states. + * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up + * from this follows a full CPU reset path via ROM code to CPU restore code. + * It returns to the caller for CPU INACTIVE and ON power states or in case + * CPU failed to transition to targeted OFF/DORMANT state. + */ + +ENTRY(omap4_cpu_suspend) + stmfd sp!, {r0-r12, lr} @ Save registers on stack + cmp r1, #0x0 + beq do_WFI @ Nothing to save, jump to WFI + mov r5, r0 + mov r6, r1 + bl omap4_get_sar_ram_base + mov r8, r0 + str r6, [r8, #L2X0_OFFSET] @ Store save state + ands r5, r5, #0x0f + orreq r8, r8, #CPU0_SAVE_OFFSET + orrne r8, r8, #CPU1_SAVE_OFFSET + + /* + * Save only needed CPU CP15 registers. VFP, breakpoint, + * performance monitor registers are not saved. Generic + * code suppose to take care of those. + */ + mov r4, sp @ Store sp + mrs r5, spsr @ Store spsr + mov r6, lr @ Store lr + stmia r8!, {r4-r6} + + /* c1 and c2 registers */ + mrc p15, 0, r4, c1, c0, 2 @ CPACR + mrc p15, 0, r5, c2, c0, 0 @ TTBR0 + mrc p15, 0, r6, c2, c0, 1 @ TTBR1 + mrc p15, 0, r7, c2, c0, 2 @ TTBCR + stmia r8!, {r4-r7} + + /* c3 and c10 registers */ + mrc p15, 0, r4, c3, c0, 0 @ DACR + mrc p15, 0, r5, c10, c2, 0 @ PRRR + mrc p15, 0, r6, c10, c2, 1 @ NMRR + stmia r8!,{r4-r6} + + /* c12, c13 and CPSR registers */ + mrc p15, 0, r4, c13, c0, 1 @ Context ID + mrc p15, 0, r5, c13, c0, 2 @ User r/w thread ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR + mrs r7, cpsr @ Store CPSR + stmia r8!, {r4-r7} + + /* c1 control register */ + mrc p15, 0, r4, c1, c0, 0 @ Save control register + stmia r8!, {r4} + + /* + * Flush all data from the L1 data cache before disabling + * SCTLR.C bit. + */ + bl v7_flush_dcache_all + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. Clearing SCTLR.C would make all the data accesses + * strongly ordered and would not hit the cache. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Invalidate L1 data cache. Even though only invalidate is + * necessary exported flush API is used here. Doing clean + * on already clean cache would be almost NOP. + */ + bl v7_flush_dcache_all + + /* + * Switch the CPU from Symmetric Multiprocessing (SMP) mode + * to AsymmetricMultiprocessing (AMP) mode by programming + * the SCU power status to DORMANT or OFF mode. + * This enables the CPU to be taken out of coherency by + * preventing the CPU from receiving cache, TLB, or BTB + * maintenance operations broadcast by other CPUs in the cluster. + */ + bl omap4_get_sar_ram_base + mov r8, r0 + ldr r9, [r8, #OMAP_TYPE_OFFSET] + cmp r9, #0x1 @ Check for HS device + bne scu_gp_set + mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR + ands r0, r0, #0x0f + ldreq r0, [r8, #SCU_OFFSET0] + ldreq r1, [r8, #L1_OFFSET0] + ldrne r0, [r8, #SCU_OFFSET1] + ldrne r1, [r8, #L1_OFFSET0] + stmfd r13!, {r4-r12, r14} + ldr r12, =SCU_POWER_SECURE_INDEX + dsb + smc #0 + dsb + ldmfd r13!, {r4-r12, r14} + b skip_scu_gp_set +scu_gp_set: + mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR + ands r0, r0, #0x0f + ldreq r1, [r8, #SCU_OFFSET0] + ldrne r1, [r8, #SCU_OFFSET1] + bl omap4_get_scu_base + bl scu_power_mode +skip_scu_gp_set: + isb + dsb + +#ifdef CONFIG_CACHE_L2X0 + /* + * Clean and invalidate the L2 cache. + * Common cache-l2x0.c functions can't be used here since it + * uses spinlocks. We are out of coherency here with data cache + * disabled. The spinlock implementation uses exclusive load/store + * instruction which can fail without data cache being enabled. + * OMAP4 hardware doesn't support exclusive monitor which can + * overcome exclusive access issue. Because of this, CPU can + * lead to deadlock. + */ +l2x_clean_inv: + bl omap4_get_sar_ram_base + mov r8, r0 + ldr r0, [r8, #L2X0_OFFSET] + cmp r0, #3 + bne do_WFI +#ifdef CONFIG_PL310_ERRATA_727915 + mov r0, #0x03 + mov r12, #0x100 + dsb + smc #0 + dsb +#endif + bl omap4_get_l2cache_base + mov r2, r0 + mov r0, #0xff + str r0, [r2, #L2X0_CLEAN_WAY] +wait: + ldr r0, [r2, #L2X0_CLEAN_WAY] + ands r0, r0, #0xff + bne wait +#ifdef CONFIG_PL310_ERRATA_727915 + mov r0, #0x00 + mov r12, #0x100 + dsb + smc #0 + dsb +#endif +#endif + +do_WFI: +#ifdef CONFIG_CACHE_L2X0 + /* Issue cache sync before WFI to drain L2X0 buffer */ +l2x_sync: + bl omap4_get_l2cache_base + mov r2, r0 + mov r0, #0x0 + str r0, [r2, #L2X0_CACHE_SYNC] +sync: + ldr r0, [r2, #L2X0_CACHE_SYNC] + ands r0, r0, #0x1 + bne sync +#endif + /* + * Execute an ISB instruction to ensure that all of the + * CP15 register changes have been committed. + */ + isb + + /* + * Execute a barrier instruction to ensure that all cache, + * TLB and branch predictor maintenance operations issued + * by any CPU in the cluster have completed. + */ + dsb + dmb + + /* + * Execute a WFI instruction and wait until the + * STANDBYWFI output is asserted to indicate that the + * CPU is in idle and low power state. CPU can specualatively + * prefetch the instructions so add NOPs after WFI. Sixteen + * NOPs as per Cortex-A9 pipeline. + */ + wfi @ Wait For Interrupt + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + /* + * CPU is here when it failed to enter OFF/DORMANT or + * no low power state was attempted. + */ + mrc p15, 0, r0, c1, c0, 0 + tst r0, #(1 << 2) @ Check C bit enabled? + orreq r0, r0, #(1 << 2) @ Enable the C bit + mcreq p15, 0, r0, c1, c0, 0 + isb + + /* + * Ensure the CPU power state is set to NORMAL in + * SCU power state so that CPU is back in coherency. + * In non-coherent mode CPU can lock-up and lead to + * system deadlock. + */ + bl omap4_get_sar_ram_base + mov r8, r0 + ldr r9, [r8, #OMAP_TYPE_OFFSET] + cmp r9, #0x1 @ Check for HS device + bne scu_gp_clear + mov r0, #SCU_PM_NORMAL + mov r1, #0x00 + stmfd r13!, {r4-r12, r14} + ldr r12, =SCU_POWER_SECURE_INDEX + dsb + smc #0 + dsb + ldmfd r13!, {r4-r12, r14} + b skip_scu_gp_clear +scu_gp_clear: + bl omap4_get_scu_base + mov r1, #SCU_PM_NORMAL + bl scu_power_mode +skip_scu_gp_clear: + isb + dsb + + ldmfd sp!, {r0-r12, pc} @ Restore regs and return +ENDPROC(omap4_cpu_suspend) + +/* + * ============================ + * == CPU resume entry point == + * ============================ + * + * void omap4_cpu_resume(void) + * + * ROM code jumps to this function while waking up from CPU + * OFF or DORMANT state. Physical address of the function is + * stored in the SAR RAM while entering to OFF or DORMANT mode. + */ + +ENTRY(omap4_cpu_resume) +#ifdef CONFIG_CACHE_L2X0 + /* + * Restore the L2 AUXCTRL and enable the L2 cache. + * 0x109 = Program the L2X0 AUXCTRL + * 0x102 = Enable the L2 using L2X0 CTRL + * register r0 contains value to be programmed. + * L2 cache is already invalidate by ROM code as part + * of MPUSS OFF wakeup path. + */ + ldr r2, =OMAP44XX_L2CACHE_BASE + ldr r0, [r2, #L2X0_CTRL] + and r0, #0x0f + cmp r0, #1 + beq skip_l2en @ Skip if already enabled + ldr r3, =OMAP44XX_SAR_RAM_BASE + ldr r0, [r3, #L2X0_AUXCTRL_OFFSET] + ldr r12, =0x109 @ Setup L2 AUXCTRL value + dsb + smc #0 + dsb + mov r0, #0x1 + ldr r12, =0x102 @ Enable L2 Cache controller + dsb + smc #0 + dsb +skip_l2en: +#endif + + /* + * Check the wakeup cpuid and use appropriate + * SAR BANK location for context restore. + */ + ldr r3, =OMAP44XX_SAR_RAM_BASE + mov r1, #0 + mcr p15, 0, r1, c7, c5, 0 @ Invalidate L1 I + mrc p15, 0, r0, c0, c0, 5 @ MPIDR + ands r0, r0, #0x0f + orreq r3, r3, #CPU0_SAVE_OFFSET + orrne r3, r3, #CPU1_SAVE_OFFSET + + /* Restore cp15 registers */ + ldmia r3!, {r4-r6} + mov sp, r4 @ Restore sp + msr spsr_cxsf, r5 @ Restore spsr + mov lr, r6 @ Restore lr + + /* c1 and c2 registers */ + ldmia r3!, {r4-r7} + mcr p15, 0, r4, c1, c0, 2 @ CPACR + mcr p15, 0, r5, c2, c0, 0 @ TTBR0 + mcr p15, 0, r6, c2, c0, 1 @ TTBR1 + mcr p15, 0, r7, c2, c0, 2 @ TTBCR + + /* c3 and c10 registers */ + ldmia r3!,{r4-r6} + mcr p15, 0, r4, c3, c0, 0 @ DACR + mcr p15, 0, r5, c10, c2, 0 @ PRRR + mcr p15, 0, r6, c10, c2, 1 @ NMRR + + /* c12, c13 and CPSR registers */ + ldmia r3!,{r4-r7} + mcr p15, 0, r4, c13, c0, 1 @ Context ID + mcr p15, 0, r5, c13, c0, 2 @ User r/w thread ID + mcr p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR + msr cpsr, r7 @ store cpsr + + /* + * Enabling MMU here. Page entry needs to be altered + * to create temporary 1:1 map and then resore the entry + * ones MMU is enabled + */ + mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl + and r7, #0x7 @ Extract N (0:2) to decide + cmp r7, #0x0 @ TTBR0/TTBR1 + beq use_ttbr0 +ttbr_error: + b ttbr_error @ Only N = 0 supported +use_ttbr0: + mrc p15, 0, r2, c2, c0, 0 @ Read TTBR0 + ldr r5, =TTRBIT_MASK + and r2, r5 + mov r4, pc + ldr r5, =TABLE_INDEX_MASK + and r4, r5 @ r4 = 31 to 20 bits of pc + ldr r1, =TABLE_ENTRY + add r1, r1, r4 @ r1 has value of table entry + lsr r4, #18 @ Address of table entry + add r2, r4 @ r2 - location to be modified + + /* Ensure the modified entry makes it to main memory */ +#ifdef CONFIG_CACHE_L2X0 + ldr r5, =OMAP44XX_L2CACHE_BASE + str r2, [r5, #L2X0_CLEAN_INV_LINE_PA] +wait_l2: + ldr r0, [r5, #L2X0_CLEAN_INV_LINE_PA] + ands r0, #1 + bne wait_l2 +#endif + + /* Storing previous entry of location being modified */ + ldr r5, =OMAP44XX_SAR_RAM_BASE + ldr r4, [r2] + mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR + ands r0, r0, #0x0f + streq r4, [r5, #MMU_OFFSET0] @ Modify the table entry + strne r4, [r5, #MMU_OFFSET1] + str r1, [r2] + + /* + * Storing address of entry being modified + * It will be restored after enabling MMU + */ + ldr r5, =OMAP44XX_SAR_RAM_BASE + mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR + ands r0, r0, #0x0f + orreq r5, r5, #MMU_OFFSET0 + orrne r5, r5, #MMU_OFFSET1 + str r2, [r5, #TABLE_ADDRESS_OFFSET] + mov r0, #0 + mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer + mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB + mcr p15, 0, r0, c8, c5, 0 @ Invalidate ITLB + mcr p15, 0, r0, c8, c6, 0 @ Invalidate DTLB + + /* + * Restore control register but don't enable Data caches here. + * Caches will be enabled after restoring MMU table entry. + */ + ldmia r3!, {r4} + str r4, [r5, #CR_VALUE_OFFSET] @ Store previous value of CR + ldr r2, =CACHE_DISABLE_MASK + and r4, r2 + mcr p15, 0, r4, c1, c0, 0 + isb + dsb + ldr r0, =mmu_on_label + bx r0 +mmu_on_label: + /* Set up the per-CPU stacks */ + bl cpu_init + + /* + * Restore the MMU table entry that was modified for + * enabling MMU. + */ + bl omap4_get_sar_ram_base + mov r8, r0 + mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR + ands r0, r0, #0x0f + orreq r8, r8, #MMU_OFFSET0 @ Get address of entry that.. + orrne r8, r8, #MMU_OFFSET1 @ was modified + ldr r2, [r8, #TABLE_ADDRESS_OFFSET] + ldr r3, =local_va2pa_offet + add r2, r2, r3 + ldr r0, [r8] @ Get the previous value.. + str r0, [r2] @ which needs to be restored + mov r0, #0 + mcr p15, 0, r0, c7, c1, 6 @ flush TLB and issue barriers + mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer + mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB + mcr p15, 0, r0, c8, c5, 0 @ Invalidate ITLB + mcr p15, 0, r0, c8, c6, 0 @ Invalidate DTLB + dsb + isb + ldr r0, [r8, #CR_VALUE_OFFSET] @ Restore the Control register + mcr p15, 0, r0, c1, c0, 0 @ with caches enabled. + isb + + ldmfd sp!, {r0-r12, pc} @ restore regs and return + + .equ local_va2pa_offet, (PLAT_PHYS_OFFSET + PAGE_OFFSET) + +ENDPROC(omap4_cpu_resume) + +#endif diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c index f438cf4..4eac1bc 100644 --- a/arch/arm/mach-omap2/smartreflex-class3.c +++ b/arch/arm/mach-omap2/smartreflex-class3.c @@ -32,7 +32,7 @@ static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset) omap_vp_disable(voltdm); sr_disable(voltdm); if (is_volt_reset) - omap_voltage_reset(voltdm); + voltdm_reset(voltdm); return 0; } diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index fb7dc52..f8c6305 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -62,6 +62,7 @@ static LIST_HEAD(sr_list); static struct omap_sr_class_data *sr_class; static struct omap_sr_pmic_data *sr_pmic_data; +static struct dentry *sr_dbg_dir; static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) { @@ -143,7 +144,7 @@ static irqreturn_t sr_interrupt(int irq, void *data) sr_write_reg(sr_info, IRQSTATUS, status); } - if (sr_class->class_type == SR_CLASS2 && sr_class->notify) + if (sr_class->notify) sr_class->notify(sr_info->voltdm, status); return IRQ_HANDLED; @@ -258,9 +259,7 @@ static int sr_late_init(struct omap_sr *sr_info) struct resource *mem; int ret = 0; - if (sr_class->class_type == SR_CLASS2 && - sr_class->notify_flags && sr_info->irq) { - + if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name); if (name == NULL) { ret = -ENOMEM; @@ -270,6 +269,7 @@ static int sr_late_init(struct omap_sr *sr_info) 0, name, (void *)sr_info); if (ret) goto error; + disable_irq(sr_info->irq); } if (pdata && pdata->enable_on_init) @@ -278,16 +278,16 @@ static int sr_late_init(struct omap_sr *sr_info) return ret; error: - iounmap(sr_info->base); - mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - list_del(&sr_info->node); - dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" - "interrupt handler. Smartreflex will" - "not function as desired\n", __func__); - kfree(name); - kfree(sr_info); - return ret; + iounmap(sr_info->base); + mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); + list_del(&sr_info->node); + dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" + "interrupt handler. Smartreflex will" + "not function as desired\n", __func__); + kfree(name); + kfree(sr_info); + return ret; } static void sr_v1_disable(struct omap_sr *sr) @@ -808,10 +808,13 @@ static int omap_sr_autocomp_store(void *data, u64 val) return -EINVAL; } - if (!val) - sr_stop_vddautocomp(sr_info); - else - sr_start_vddautocomp(sr_info); + /* control enable/disable only if there is a delta in value */ + if (sr_info->autocomp_active != val) { + if (!val) + sr_stop_vddautocomp(sr_info); + else + sr_start_vddautocomp(sr_info); + } return 0; } @@ -824,9 +827,10 @@ static int __init omap_sr_probe(struct platform_device *pdev) struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); struct omap_sr_data *pdata = pdev->dev.platform_data; struct resource *mem, *irq; - struct dentry *vdd_dbg_dir, *nvalue_dir; + struct dentry *nvalue_dir; struct omap_volt_data *volt_data; int i, ret = 0; + char *name; if (!sr_info) { dev_err(&pdev->dev, "%s: unable to allocate sr_info\n", @@ -896,18 +900,25 @@ static int __init omap_sr_probe(struct platform_device *pdev) } dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__); + if (!sr_dbg_dir) { + sr_dbg_dir = debugfs_create_dir("smartreflex", NULL); + if (!sr_dbg_dir) { + ret = PTR_ERR(sr_dbg_dir); + pr_err("%s:sr debugfs dir creation failed(%d)\n", + __func__, ret); + goto err_iounmap; + } + } - /* - * If the voltage domain debugfs directory is not created, do - * not try to create rest of the debugfs entries. - */ - vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm); - if (!vdd_dbg_dir) { - ret = -EINVAL; + name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name); + if (!name) { + dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n", + __func__); + ret = -ENOMEM; goto err_iounmap; } - - sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir); + sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir); + kfree(name); if (IS_ERR(sr_info->dbg_dir)) { dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", __func__); diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h index 5f35b9e..fd61498 100644 --- a/arch/arm/mach-omap2/smartreflex.h +++ b/arch/arm/mach-omap2/smartreflex.h @@ -152,6 +152,15 @@ struct omap_sr_pmic_data { void (*sr_pmic_init) (void); }; +/** + * struct omap_smartreflex_dev_attr - Smartreflex Device attribute. + * + * @sensor_voltdm_name: Name of voltdomain of SR instance + */ +struct omap_smartreflex_dev_attr { + const char *sensor_voltdm_name; +}; + #ifdef CONFIG_OMAP_SMARTREFLEX /* * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR. diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index 10d3c5e..0b74f5b 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -82,6 +82,7 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user) struct omap_sr_data *sr_data; struct omap_device *od; struct omap_volt_data *volt_data; + struct omap_smartreflex_dev_attr *sr_dev_attr; char *name = "smartreflex"; static int i; @@ -92,9 +93,11 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user) return -ENOMEM; } - if (!oh->vdd_name) { + sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr; + if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) { pr_err("%s: No voltage domain specified for %s." - "Cannot initialize\n", __func__, oh->name); + "Cannot initialize\n", __func__, + oh->name); goto exit; } @@ -102,10 +105,10 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user) sr_data->senn_mod = 0x1; sr_data->senp_mod = 0x1; - sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name); + sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name); if (IS_ERR(sr_data->voltdm)) { pr_err("%s: Unable to get voltage domain pointer for VDD %s\n", - __func__, oh->vdd_name); + __func__, sr_dev_attr->sensor_voltdm_name); goto exit; } diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c new file mode 100644 index 0000000..2cf520d --- /dev/null +++ b/arch/arm/mach-omap2/vc.c @@ -0,0 +1,454 @@ +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/init.h> + +#include <plat/cpu.h> + +#include "voltage.h" +#include "vc.h" +#include "prm-regbits-34xx.h" +#include "prm-regbits-44xx.h" +#include "prm44xx.h" + +/** + * struct omap_vc_channel_cfg - describe the cfg_channel bitfield + * @sa: bit for slave address + * @rav: bit for voltage configuration register + * @rac: bit for command configuration register + * @racen: enable bit for RAC + * @cmd: bit for command value set selection + * + * Channel configuration bits, common for OMAP3+ + * OMAP3 register: PRM_VC_CH_CONF + * OMAP4 register: PRM_VC_CFG_CHANNEL + * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG + */ +struct omap_vc_channel_cfg { + u8 sa; + u8 rav; + u8 rac; + u8 racen; + u8 cmd; +}; + +static struct omap_vc_channel_cfg vc_default_channel_cfg = { + .sa = BIT(0), + .rav = BIT(1), + .rac = BIT(2), + .racen = BIT(3), + .cmd = BIT(4), +}; + +/* + * On OMAP3+, all VC channels have the above default bitfield + * configuration, except the OMAP4 MPU channel. This appears + * to be a freak accident as every other VC channel has the + * default configuration, thus creating a mutant channel config. + */ +static struct omap_vc_channel_cfg vc_mutant_channel_cfg = { + .sa = BIT(0), + .rav = BIT(2), + .rac = BIT(3), + .racen = BIT(4), + .cmd = BIT(1), +}; + +static struct omap_vc_channel_cfg *vc_cfg_bits; +#define CFG_CHANNEL_MASK 0x1f + +/** + * omap_vc_config_channel - configure VC channel to PMIC mappings + * @voltdm: pointer to voltagdomain defining the desired VC channel + * + * Configures the VC channel to PMIC mappings for the following + * PMIC settings + * - i2c slave address (SA) + * - voltage configuration address (RAV) + * - command configuration address (RAC) and enable bit (RACEN) + * - command values for ON, ONLP, RET and OFF (CMD) + * + * This function currently only allows flexible configuration of the + * non-default channel. Starting with OMAP4, there are more than 2 + * channels, with one defined as the default (on OMAP4, it's MPU.) + * Only the non-default channel can be configured. + */ +static int omap_vc_config_channel(struct voltagedomain *voltdm) +{ + struct omap_vc_channel *vc = voltdm->vc; + + /* + * For default channel, the only configurable bit is RACEN. + * All others must stay at zero (see function comment above.) + */ + if (vc->flags & OMAP_VC_CHANNEL_DEFAULT) + vc->cfg_channel &= vc_cfg_bits->racen; + + voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift, + vc->cfg_channel << vc->cfg_channel_sa_shift, + vc->common->cfg_channel_reg); + + return 0; +} + +/* Voltage scale and accessory APIs */ +int omap_vc_pre_scale(struct voltagedomain *voltdm, + unsigned long target_volt, + u8 *target_vsel, u8 *current_vsel) +{ + struct omap_vc_channel *vc = voltdm->vc; + u32 vc_cmdval; + + /* Check if sufficient pmic info is available for this vdd */ + if (!voltdm->pmic) { + pr_err("%s: Insufficient pmic info to scale the vdd_%s\n", + __func__, voltdm->name); + return -EINVAL; + } + + if (!voltdm->pmic->uv_to_vsel) { + pr_err("%s: PMIC function to convert voltage in uV to" + "vsel not registered. Hence unable to scale voltage" + "for vdd_%s\n", __func__, voltdm->name); + return -ENODATA; + } + + if (!voltdm->read || !voltdm->write) { + pr_err("%s: No read/write API for accessing vdd_%s regs\n", + __func__, voltdm->name); + return -EINVAL; + } + + *target_vsel = voltdm->pmic->uv_to_vsel(target_volt); + *current_vsel = voltdm->read(voltdm->vp->voltage); + + /* Setting the ON voltage to the new target voltage */ + vc_cmdval = voltdm->read(vc->cmdval_reg); + vc_cmdval &= ~vc->common->cmd_on_mask; + vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift); + voltdm->write(vc_cmdval, vc->cmdval_reg); + + omap_vp_update_errorgain(voltdm, target_volt); + + return 0; +} + +void omap_vc_post_scale(struct voltagedomain *voltdm, + unsigned long target_volt, + u8 target_vsel, u8 current_vsel) +{ + u32 smps_steps = 0, smps_delay = 0; + + smps_steps = abs(target_vsel - current_vsel); + /* SMPS slew rate / step size. 2us added as buffer. */ + smps_delay = ((smps_steps * voltdm->pmic->step_size) / + voltdm->pmic->slew_rate) + 2; + udelay(smps_delay); + + voltdm->curr_volt = target_volt; +} + +static int omap_vc_bypass_send_value(struct voltagedomain *voltdm, + struct omap_vc_channel *vc, u8 sa, u8 reg, u32 data) +{ + u32 loop_cnt = 0, retries_cnt = 0; + u32 vc_valid, vc_bypass_val_reg, vc_bypass_value; + + if (IS_ERR_OR_NULL(vc->common)) { + pr_err("%s voldm=%s bad value for vc->common\n", + __func__, voltdm->name); + return -EINVAL; + } + + vc_valid = vc->common->valid; + vc_bypass_val_reg = vc->common->bypass_val_reg; + vc_bypass_value = (data << vc->common->data_shift) | + (reg << vc->common->regaddr_shift) | + (sa << vc->common->slaveaddr_shift); + + voltdm->write(vc_bypass_value, vc_bypass_val_reg); + voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg); + + vc_bypass_value = voltdm->read(vc_bypass_val_reg); + /* + * Loop till the bypass command is acknowledged from the SMPS. + * NOTE: This is legacy code. The loop count and retry count needs + * to be revisited. + */ + while (!(vc_bypass_value & vc_valid)) { + loop_cnt++; + + if (retries_cnt > 10) { + pr_warning("%s: Retry count exceeded\n", __func__); + return -ETIMEDOUT; + } + + if (loop_cnt > 50) { + retries_cnt++; + loop_cnt = 0; + udelay(10); + } + vc_bypass_value = voltdm->read(vc_bypass_val_reg); + } + + return 0; + +} + +/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */ +int omap_vc_bypass_scale_voltage(struct voltagedomain *voltdm, + unsigned long target_volt) +{ + struct omap_vc_channel *vc; + u8 target_vsel, current_vsel; + int ret; + + if (IS_ERR_OR_NULL(voltdm)) { + pr_err("%s bad voldm\n", __func__); + return -EINVAL; + } + + vc = voltdm->vc; + if (IS_ERR_OR_NULL(vc)) { + pr_err("%s voldm=%s bad vc\n", __func__, voltdm->name); + return -EINVAL; + } + + ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, + ¤t_vsel); + if (ret) + return ret; + + ret = omap_vc_bypass_send_value(voltdm, vc, vc->i2c_slave_addr, + vc->volt_reg_addr, target_vsel); + if (ret) + return ret; + + omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel); + return 0; +} + +/** + * omap_vc_bypass_send_i2c_msg() - Function to control PMIC registers over SRI2C + * @voltdm: voltage domain + * @slave_addr: slave address of the device. + * @reg_addr: register address to access + * @data: what do we want to write there + * + * Many simpler PMICs with a single I2C interface still have configuration + * registers that may need population. Typical being slew rate configurations + * thermal shutdown configuration etc. When these PMICs are hooked on I2C_SR, + * this function allows these configuration registers to be accessed. + * + * WARNING: Though this could be used for voltage register configurations over + * I2C_SR, DONOT use it for that purpose, all the Voltage controller's internal + * information is bypassed using this function and must be used judiciously. + */ +int omap_vc_bypass_send_i2c_msg(struct voltagedomain *voltdm, u8 slave_addr, + u8 reg_addr, u8 data) +{ + struct omap_vc_channel *vc; + + if (IS_ERR_OR_NULL(voltdm)) { + pr_err("%s bad voldm\n", __func__); + return -EINVAL; + } + + vc = voltdm->vc; + if (IS_ERR_OR_NULL(vc)) { + pr_err("%s voldm=%s bad vc\n", __func__, voltdm->name); + return -EINVAL; + } + + return omap_vc_bypass_send_value(voltdm, vc, slave_addr, + reg_addr, data); +} + +static void __init omap3_vfsm_init(struct voltagedomain *voltdm) +{ + /* + * Voltage Manager FSM parameters init + * XXX This data should be passed in from the board file + */ + voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET); + voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET); + voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET); +} + +static void __init omap3_vc_init_channel(struct voltagedomain *voltdm) +{ + static bool is_initialized; + + if (is_initialized) + return; + + omap3_vfsm_init(voltdm); + + is_initialized = true; +} + + +/* OMAP4 specific voltage init functions */ +static void __init omap4_vc_init_channel(struct voltagedomain *voltdm) +{ + static bool is_initialized; + struct omap_voltdm_pmic *pmic = voltdm->pmic; + u32 vc_val = 0; + + if (is_initialized) + return; + + if (pmic->i2c_high_speed) { + vc_val |= pmic->i2c_hscll_low << OMAP4430_HSCLL_SHIFT; + vc_val |= pmic->i2c_hscll_high << OMAP4430_HSCLH_SHIFT; + } + + vc_val |= pmic->i2c_scll_low << OMAP4430_SCLL_SHIFT; + vc_val |= pmic->i2c_scll_high << OMAP4430_SCLH_SHIFT; + + if (vc_val) + voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET); + + is_initialized = true; +} + +/** + * omap_vc_i2c_init - initialize I2C interface to PMIC + * @voltdm: voltage domain containing VC data + * + * Use PMIC supplied seetings for I2C high-speed mode and + * master code (if set) and program the VC I2C configuration + * register. + * + * The VC I2C configuration is common to all VC channels, + * so this function only configures I2C for the first VC + * channel registers. All other VC channels will use the + * same configuration. + */ +static void __init omap_vc_i2c_init(struct voltagedomain *voltdm) +{ + struct omap_vc_channel *vc = voltdm->vc; + static bool initialized; + static bool i2c_high_speed; + u8 mcode; + + if (initialized) { + if (voltdm->pmic->i2c_high_speed != i2c_high_speed) + pr_warn("%s: I2C config for all channels must match.", + __func__); + return; + } + + i2c_high_speed = voltdm->pmic->i2c_high_speed; + if (i2c_high_speed) + voltdm->rmw(vc->common->i2c_cfg_hsen_mask, + vc->common->i2c_cfg_hsen_mask, + vc->common->i2c_cfg_reg); + + mcode = voltdm->pmic->i2c_mcode; + if (mcode) + voltdm->rmw(vc->common->i2c_mcode_mask, + mcode << __ffs(vc->common->i2c_mcode_mask), + vc->common->i2c_cfg_reg); + + initialized = true; +} + +void __init omap_vc_init_channel(struct voltagedomain *voltdm) +{ + struct omap_vc_channel *vc = voltdm->vc; + u8 on_vsel, onlp_vsel, ret_vsel, off_vsel; + u32 val; + + if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { + pr_err("%s: PMIC info requried to configure vc for" + "vdd_%s not populated.Hence cannot initialize vc\n", + __func__, voltdm->name); + return; + } + + if (!voltdm->read || !voltdm->write) { + pr_err("%s: No read/write API for accessing vdd_%s regs\n", + __func__, voltdm->name); + return; + } + + vc->cfg_channel = 0; + if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT) + vc_cfg_bits = &vc_mutant_channel_cfg; + else + vc_cfg_bits = &vc_default_channel_cfg; + + /* get PMIC/board specific settings */ + vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr; + vc->volt_reg_addr = voltdm->pmic->volt_reg_addr; + vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr; + vc->setup_time = voltdm->pmic->volt_setup_time; + + if ((vc->flags & OMAP_VC_CHANNEL_DEFAULT) && + ((vc->i2c_slave_addr == USE_DEFAULT_CHANNEL_I2C_PARAM) || + (vc->cmd_reg_addr == USE_DEFAULT_CHANNEL_I2C_PARAM) || + (vc->volt_reg_addr == USE_DEFAULT_CHANNEL_I2C_PARAM))) { + pr_err("%s: voltdm %s: default channel " + "bad config-sa=%2x vol=%2x, cmd=%2x?\n", __func__, + voltdm->name, vc->i2c_slave_addr, vc->volt_reg_addr, + vc->cmd_reg_addr); + return; + } + + /* Configure the i2c slave address for this VC */ + if (vc->i2c_slave_addr != USE_DEFAULT_CHANNEL_I2C_PARAM) { + voltdm->rmw(vc->smps_sa_mask, + vc->i2c_slave_addr << __ffs(vc->smps_sa_mask), + vc->common->smps_sa_reg); + vc->cfg_channel |= vc_cfg_bits->sa; + } + + /* + * Configure the PMIC register addresses. + */ + if (vc->volt_reg_addr != USE_DEFAULT_CHANNEL_I2C_PARAM) { + voltdm->rmw(vc->smps_volra_mask, + vc->volt_reg_addr << __ffs(vc->smps_volra_mask), + vc->common->smps_volra_reg); + vc->cfg_channel |= vc_cfg_bits->rav; + } + + if (vc->cmd_reg_addr != USE_DEFAULT_CHANNEL_I2C_PARAM) { + voltdm->rmw(vc->smps_cmdra_mask, + vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask), + vc->common->smps_cmdra_reg); + vc->cfg_channel |= vc_cfg_bits->rac; + } + + /* If voltage and cmd regs are same, we can use cmdra register */ + if (vc->volt_reg_addr == vc->cmd_reg_addr) + vc->cfg_channel |= vc_cfg_bits->racen; + + /* Set up the on, inactive, retention and off voltage */ + on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt); + onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt); + ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt); + off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt); + val = ((on_vsel << vc->common->cmd_on_shift) | + (onlp_vsel << vc->common->cmd_onlp_shift) | + (ret_vsel << vc->common->cmd_ret_shift) | + (off_vsel << vc->common->cmd_off_shift)); + voltdm->write(val, vc->cmdval_reg); + vc->cfg_channel |= vc_cfg_bits->cmd; + + /* Channel configuration */ + omap_vc_config_channel(voltdm); + + /* Configure the setup times */ + voltdm->rmw(voltdm->vfsm->voltsetup_mask, + vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask), + voltdm->vfsm->voltsetup_reg); + + omap_vc_i2c_init(voltdm); + + if (cpu_is_omap34xx()) + omap3_vc_init_channel(voltdm); + else if (cpu_is_omap44xx()) + omap4_vc_init_channel(voltdm); +} + diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h index e776777..cf20f47 100644 --- a/arch/arm/mach-omap2/vc.h +++ b/arch/arm/mach-omap2/vc.h @@ -19,8 +19,10 @@ #include <linux/kernel.h> +struct voltagedomain; + /** - * struct omap_vc_common_data - per-VC register/bitfield data + * struct omap_vc_common - per-VC register/bitfield data * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start @@ -33,15 +35,19 @@ * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register + * @i2c_cfg_reg: I2C configuration register offset + * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register + * @i2c_mcode_mask: MCODE field mask for I2C config register * * XXX One of cmd_on_mask and cmd_on_shift are not needed * XXX VALID should probably be a shift, not a mask */ -struct omap_vc_common_data { +struct omap_vc_common { u32 cmd_on_mask; u32 valid; u8 smps_sa_reg; u8 smps_volra_reg; + u8 smps_cmdra_reg; u8 bypass_val_reg; u8 data_shift; u8 slaveaddr_shift; @@ -50,34 +56,60 @@ struct omap_vc_common_data { u8 cmd_onlp_shift; u8 cmd_ret_shift; u8 cmd_off_shift; + u8 cfg_channel_reg; + u8 i2c_cfg_reg; + u8 i2c_cfg_hsen_mask; + u8 i2c_mcode_mask; }; +/* omap_vc_channel.flags values */ +#define OMAP_VC_CHANNEL_DEFAULT BIT(0) +#define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1) + /** - * struct omap_vc_instance_data - VC per-instance data - * @vc_common: pointer to VC common data for this platform - * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register + * struct omap_vc_channel - VC per-instance data + * @flags: VC channel-specific flags (optional) + * @common: pointer to VC common data for this platform + * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register - * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register - * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register - * - * XXX It is not necessary to have both a *_mask and a *_shift - - * remove one */ -struct omap_vc_instance_data { - const struct omap_vc_common_data *vc_common; +struct omap_vc_channel { + u8 flags; + + /* channel state */ + u16 i2c_slave_addr; + u16 volt_reg_addr; + u16 cmd_reg_addr; + u8 cfg_channel; + u16 setup_time; + bool i2c_high_speed; + + /* register access data */ + const struct omap_vc_common *common; u32 smps_sa_mask; u32 smps_volra_mask; + u32 smps_cmdra_mask; u8 cmdval_reg; - u8 smps_sa_shift; - u8 smps_volra_shift; + u8 cfg_channel_sa_shift; }; -extern struct omap_vc_instance_data omap3_vc1_data; -extern struct omap_vc_instance_data omap3_vc2_data; +extern struct omap_vc_channel omap3_vc_mpu; +extern struct omap_vc_channel omap3_vc_core; -extern struct omap_vc_instance_data omap4_vc_mpu_data; -extern struct omap_vc_instance_data omap4_vc_iva_data; -extern struct omap_vc_instance_data omap4_vc_core_data; +extern struct omap_vc_channel omap4_vc_mpu; +extern struct omap_vc_channel omap4_vc_iva; +extern struct omap_vc_channel omap4_vc_core; +void omap_vc_init_channel(struct voltagedomain *voltdm); +int omap_vc_pre_scale(struct voltagedomain *voltdm, + unsigned long target_volt, + u8 *target_vsel, u8 *current_vsel); +void omap_vc_post_scale(struct voltagedomain *voltdm, + unsigned long target_volt, + u8 target_vsel, u8 current_vsel); +int omap_vc_bypass_scale_voltage(struct voltagedomain *voltdm, + unsigned long target_volt); +int omap_vc_bypass_send_i2c_msg(struct voltagedomain *voltdm, + u8 slave_addr, u8 reg_addr, u8 data); #endif diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c index f37dc4b..95d7701 100644 --- a/arch/arm/mach-omap2/vc3xxx_data.c +++ b/arch/arm/mach-omap2/vc3xxx_data.c @@ -29,9 +29,10 @@ * VC data common to 34xx/36xx chips * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. */ -static struct omap_vc_common_data omap3_vc_common = { +static struct omap_vc_common omap3_vc_common = { .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET, .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET, + .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET, .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET, .data_shift = OMAP3430_DATA_SHIFT, .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT, @@ -42,22 +43,26 @@ static struct omap_vc_common_data omap3_vc_common = { .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT, .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, + .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET, + .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK, + .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET, + .i2c_mcode_mask = OMAP3430_MCODE_MASK, }; -struct omap_vc_instance_data omap3_vc1_data = { - .vc_common = &omap3_vc_common, +struct omap_vc_channel omap3_vc_mpu = { + .common = &omap3_vc_common, .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET, - .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT, .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK, - .smps_volra_shift = OMAP3430_VOLRA0_SHIFT, .smps_volra_mask = OMAP3430_VOLRA0_MASK, + .smps_cmdra_mask = OMAP3430_CMDRA0_MASK, + .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT, }; -struct omap_vc_instance_data omap3_vc2_data = { - .vc_common = &omap3_vc_common, +struct omap_vc_channel omap3_vc_core = { + .common = &omap3_vc_common, .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET, - .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT, .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK, - .smps_volra_shift = OMAP3430_VOLRA1_SHIFT, .smps_volra_mask = OMAP3430_VOLRA1_MASK, + .smps_cmdra_mask = OMAP3430_CMDRA1_MASK, + .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT, }; diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c index a98da8d..0a4fc37 100644 --- a/arch/arm/mach-omap2/vc44xx_data.c +++ b/arch/arm/mach-omap2/vc44xx_data.c @@ -30,9 +30,10 @@ * VC data common to 44xx chips * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. */ -static const struct omap_vc_common_data omap4_vc_common = { +static const struct omap_vc_common omap4_vc_common = { .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET, .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET, + .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET, .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET, .data_shift = OMAP4430_DATA_SHIFT, .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT, @@ -43,33 +44,38 @@ static const struct omap_vc_common_data omap4_vc_common = { .cmd_onlp_shift = OMAP4430_ONLP_SHIFT, .cmd_ret_shift = OMAP4430_RET_SHIFT, .cmd_off_shift = OMAP4430_OFF_SHIFT, + .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET, + .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET, + .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK, + .i2c_mcode_mask = OMAP4430_HSMCODE_MASK, }; /* VC instance data for each controllable voltage line */ -struct omap_vc_instance_data omap4_vc_mpu_data = { - .vc_common = &omap4_vc_common, +struct omap_vc_channel omap4_vc_mpu = { + .flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT, + .common = &omap4_vc_common, .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, - .smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT, .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, - .smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT, .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK, + .smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK, + .cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT, }; -struct omap_vc_instance_data omap4_vc_iva_data = { - .vc_common = &omap4_vc_common, +struct omap_vc_channel omap4_vc_iva = { + .common = &omap4_vc_common, .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET, - .smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT, .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK, - .smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT, .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK, + .smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK, + .cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT, }; -struct omap_vc_instance_data omap4_vc_core_data = { - .vc_common = &omap4_vc_common, +struct omap_vc_channel omap4_vc_core = { + .common = &omap4_vc_common, .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET, - .smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT, .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK, - .smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT, .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK, + .smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK, + .cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT, }; diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index 9ef3789..a501597 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -36,633 +36,51 @@ #include "control.h" #include "voltage.h" +#include "powerdomain.h" #include "vc.h" #include "vp.h" -#define VOLTAGE_DIR_SIZE 16 +static LIST_HEAD(voltdm_list); - -static struct omap_vdd_info **vdd_info; - -/* - * Number of scalable voltage domains. - */ -static int nr_scalable_vdd; - -/* XXX document */ -static s16 prm_mod_offs; -static s16 prm_irqst_ocp_mod_offs; - -static struct dentry *voltage_dir; - -/* Init function pointers */ -static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, - unsigned long target_volt); - -static u32 omap3_voltage_read_reg(u16 mod, u8 offset) -{ - return omap2_prm_read_mod_reg(mod, offset); -} - -static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset) +static int __init _config_common_vdd_data(struct voltagedomain *voltdm) { - omap2_prm_write_mod_reg(val, mod, offset); -} - -static u32 omap4_voltage_read_reg(u16 mod, u8 offset) -{ - return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, - mod, offset); -} - -static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset) -{ - omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset); -} - -static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) -{ - char *sys_ck_name; struct clk *sys_ck; - u32 sys_clk_speed, timeout_val, waittime; - - /* - * XXX Clockfw should handle this, or this should be in a - * struct record - */ - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - sys_ck_name = "sys_ck"; - else if (cpu_is_omap44xx()) - sys_ck_name = "sys_clkin_ck"; - else - return -EINVAL; /* * Sys clk rate is require to calculate vp timeout value and * smpswaittimemin and smpswaittimemax. */ - sys_ck = clk_get(NULL, sys_ck_name); + sys_ck = clk_get(NULL, voltdm->sys_clk.name); if (IS_ERR(sys_ck)) { pr_warning("%s: Could not get the sys clk to calculate" - "various vdd_%s params\n", __func__, vdd->voltdm.name); + "various vdd_%s params\n", __func__, voltdm->name); return -EINVAL; } - sys_clk_speed = clk_get_rate(sys_ck); - clk_put(sys_ck); - /* Divide to avoid overflow */ - sys_clk_speed /= 1000; + voltdm->sys_clk.rate = clk_get_rate(sys_ck); + WARN_ON(!voltdm->sys_clk.rate); /* Generic voltage parameters */ - vdd->volt_scale = vp_forceupdate_scale_voltage; - vdd->vp_enabled = false; - - vdd->vp_rt_data.vpconfig_erroroffset = - (vdd->pmic_info->vp_erroroffset << - vdd->vp_data->vp_common->vpconfig_erroroffset_shift); - - timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000; - vdd->vp_rt_data.vlimitto_timeout = timeout_val; - vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin; - vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax; - - waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) * - sys_clk_speed) / 1000; - vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime; - vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime; - vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin; - vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax; - - return 0; -} - -/* Voltage debugfs support */ -static int vp_volt_debug_get(void *data, u64 *val) -{ - struct omap_vdd_info *vdd = (struct omap_vdd_info *) data; - u8 vsel; - - if (!vdd) { - pr_warning("Wrong paramater passed\n"); - return -EINVAL; - } - - vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); - - if (!vdd->pmic_info->vsel_to_uv) { - pr_warning("PMIC function to convert vsel to voltage" - "in uV not registerd\n"); - return -EINVAL; - } - - *val = vdd->pmic_info->vsel_to_uv(vsel); - return 0; -} - -static int nom_volt_debug_get(void *data, u64 *val) -{ - struct omap_vdd_info *vdd = (struct omap_vdd_info *) data; - - if (!vdd) { - pr_warning("Wrong paramater passed\n"); - return -EINVAL; - } - - *val = omap_voltage_get_nom_volt(&vdd->voltdm); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL, - "%llu\n"); -static void vp_latch_vsel(struct omap_vdd_info *vdd) -{ - u32 vpconfig; - unsigned long uvdc; - char vsel; - - uvdc = omap_voltage_get_nom_volt(&vdd->voltdm); - if (!uvdc) { - pr_warning("%s: unable to find current voltage for vdd_%s\n", - __func__, vdd->voltdm.name); - return; - } - - if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) { - pr_warning("%s: PMIC function to convert voltage in uV to" - " vsel not registered\n", __func__); - return; - } - - vsel = vdd->pmic_info->uv_to_vsel(uvdc); - - vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); - vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask | - vdd->vp_data->vp_common->vpconfig_initvdd); - vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift; - - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - - /* Trigger initVDD value copy to voltage processor */ - vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd), - prm_mod_offs, vdd->vp_data->vpconfig); - - /* Clear initVDD copy trigger bit */ - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); -} - -/* Generic voltage init functions */ -static void __init vp_init(struct omap_vdd_info *vdd) -{ - u32 vp_val; - - if (!vdd->read_reg || !vdd->write_reg) { - pr_err("%s: No read/write API for accessing vdd_%s regs\n", - __func__, vdd->voltdm.name); - return; - } - - vp_val = vdd->vp_rt_data.vpconfig_erroroffset | - (vdd->vp_rt_data.vpconfig_errorgain << - vdd->vp_data->vp_common->vpconfig_errorgain_shift) | - vdd->vp_data->vp_common->vpconfig_timeouten; - vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig); - - vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin << - vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) | - (vdd->vp_rt_data.vstepmin_stepmin << - vdd->vp_data->vp_common->vstepmin_stepmin_shift)); - vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin); - - vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax << - vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) | - (vdd->vp_rt_data.vstepmax_stepmax << - vdd->vp_data->vp_common->vstepmax_stepmax_shift)); - vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax); - - vp_val = ((vdd->vp_rt_data.vlimitto_vddmax << - vdd->vp_data->vp_common->vlimitto_vddmax_shift) | - (vdd->vp_rt_data.vlimitto_vddmin << - vdd->vp_data->vp_common->vlimitto_vddmin_shift) | - (vdd->vp_rt_data.vlimitto_timeout << - vdd->vp_data->vp_common->vlimitto_timeout_shift)); - vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto); -} - -static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) -{ - char *name; - - name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL); - if (!name) { - pr_warning("%s: Unable to allocate memory for debugfs" - " directory name for vdd_%s", - __func__, vdd->voltdm.name); - return; - } - strcpy(name, "vdd_"); - strcat(name, vdd->voltdm.name); - - vdd->debug_dir = debugfs_create_dir(name, voltage_dir); - kfree(name); - if (IS_ERR(vdd->debug_dir)) { - pr_warning("%s: Unable to create debugfs directory for" - " vdd_%s\n", __func__, vdd->voltdm.name); - vdd->debug_dir = NULL; - return; - } - - (void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir, - &(vdd->vp_rt_data.vpconfig_errorgain)); - (void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO, - vdd->debug_dir, - &(vdd->vp_rt_data.vstepmin_smpswaittimemin)); - (void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir, - &(vdd->vp_rt_data.vstepmin_stepmin)); - (void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO, - vdd->debug_dir, - &(vdd->vp_rt_data.vstepmax_smpswaittimemax)); - (void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir, - &(vdd->vp_rt_data.vstepmax_stepmax)); - (void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir, - &(vdd->vp_rt_data.vlimitto_vddmax)); - (void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir, - &(vdd->vp_rt_data.vlimitto_vddmin)); - (void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir, - &(vdd->vp_rt_data.vlimitto_timeout)); - (void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir, - (void *) vdd, &vp_volt_debug_fops); - (void) debugfs_create_file("curr_nominal_volt", S_IRUGO, - vdd->debug_dir, (void *) vdd, - &nom_volt_debug_fops); -} - -/* Voltage scale and accessory APIs */ -static int _pre_volt_scale(struct omap_vdd_info *vdd, - unsigned long target_volt, u8 *target_vsel, u8 *current_vsel) -{ - struct omap_volt_data *volt_data; - const struct omap_vc_common_data *vc_common; - const struct omap_vp_common_data *vp_common; - u32 vc_cmdval, vp_errgain_val; - - vc_common = vdd->vc_data->vc_common; - vp_common = vdd->vp_data->vp_common; - - /* Check if suffiecient pmic info is available for this vdd */ - if (!vdd->pmic_info) { - pr_err("%s: Insufficient pmic info to scale the vdd_%s\n", - __func__, vdd->voltdm.name); - return -EINVAL; - } + voltdm->scale = omap_vp_forceupdate_scale; - if (!vdd->pmic_info->uv_to_vsel) { - pr_err("%s: PMIC function to convert voltage in uV to" - "vsel not registered. Hence unable to scale voltage" - "for vdd_%s\n", __func__, vdd->voltdm.name); - return -ENODATA; - } - - if (!vdd->read_reg || !vdd->write_reg) { - pr_err("%s: No read/write API for accessing vdd_%s regs\n", - __func__, vdd->voltdm.name); - return -EINVAL; - } - - /* Get volt_data corresponding to target_volt */ - volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt); - if (IS_ERR(volt_data)) - volt_data = NULL; - - *target_vsel = vdd->pmic_info->uv_to_vsel(target_volt); - *current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); - - /* Setting the ON voltage to the new target voltage */ - vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg); - vc_cmdval &= ~vc_common->cmd_on_mask; - vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift); - vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg); - - /* Setting vp errorgain based on the voltage */ - if (volt_data) { - vp_errgain_val = vdd->read_reg(prm_mod_offs, - vdd->vp_data->vpconfig); - vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain; - vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask; - vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain << - vp_common->vpconfig_errorgain_shift; - vdd->write_reg(vp_errgain_val, prm_mod_offs, - vdd->vp_data->vpconfig); - } - - return 0; -} - -static void _post_volt_scale(struct omap_vdd_info *vdd, - unsigned long target_volt, u8 target_vsel, u8 current_vsel) -{ - u32 smps_steps = 0, smps_delay = 0; - - smps_steps = abs(target_vsel - current_vsel); - /* SMPS slew rate / step size. 2us added as buffer. */ - smps_delay = ((smps_steps * vdd->pmic_info->step_size) / - vdd->pmic_info->slew_rate) + 2; - udelay(smps_delay); - - vdd->curr_volt = target_volt; -} - -/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */ -static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd, - unsigned long target_volt) -{ - u32 loop_cnt = 0, retries_cnt = 0; - u32 vc_valid, vc_bypass_val_reg, vc_bypass_value; - u8 target_vsel, current_vsel; - int ret; - - ret = _pre_volt_scale(vdd, target_volt, &target_vsel, ¤t_vsel); - if (ret) - return ret; - - vc_valid = vdd->vc_data->vc_common->valid; - vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg; - vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) | - (vdd->pmic_info->pmic_reg << - vdd->vc_data->vc_common->regaddr_shift) | - (vdd->pmic_info->i2c_slave_addr << - vdd->vc_data->vc_common->slaveaddr_shift); - - vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg); - vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs, - vc_bypass_val_reg); - - vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg); - /* - * Loop till the bypass command is acknowledged from the SMPS. - * NOTE: This is legacy code. The loop count and retry count needs - * to be revisited. - */ - while (!(vc_bypass_value & vc_valid)) { - loop_cnt++; - - if (retries_cnt > 10) { - pr_warning("%s: Retry count exceeded\n", __func__); - return -ETIMEDOUT; - } - - if (loop_cnt > 50) { - retries_cnt++; - loop_cnt = 0; - udelay(10); - } - vc_bypass_value = vdd->read_reg(prm_mod_offs, - vc_bypass_val_reg); - } - - _post_volt_scale(vdd, target_volt, target_vsel, current_vsel); return 0; } -/* VP force update method of voltage scaling */ -static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, - unsigned long target_volt) -{ - u32 vpconfig; - u8 target_vsel, current_vsel, prm_irqst_reg; - int ret, timeout = 0; - - ret = _pre_volt_scale(vdd, target_volt, &target_vsel, ¤t_vsel); - if (ret) - return ret; - - prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg; - - /* - * Clear all pending TransactionDone interrupt/status. Typical latency - * is <3us - */ - while (timeout++ < VP_TRANXDONE_TIMEOUT) { - vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status, - prm_irqst_ocp_mod_offs, prm_irqst_reg); - if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status)) - break; - udelay(1); - } - if (timeout >= VP_TRANXDONE_TIMEOUT) { - pr_warning("%s: vdd_%s TRANXDONE timeout exceeded." - "Voltage change aborted", __func__, vdd->voltdm.name); - return -ETIMEDOUT; - } - - /* Configure for VP-Force Update */ - vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); - vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd | - vdd->vp_data->vp_common->vpconfig_forceupdate | - vdd->vp_data->vp_common->vpconfig_initvoltage_mask); - vpconfig |= ((target_vsel << - vdd->vp_data->vp_common->vpconfig_initvoltage_shift)); - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - - /* Trigger initVDD value copy to voltage processor */ - vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd; - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - - /* Force update of voltage */ - vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate; - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - - /* - * Wait for TransactionDone. Typical latency is <200us. - * Depends on SMPSWAITTIMEMIN/MAX and voltage change - */ - timeout = 0; - omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status), - VP_TRANXDONE_TIMEOUT, timeout); - if (timeout >= VP_TRANXDONE_TIMEOUT) - pr_err("%s: vdd_%s TRANXDONE timeout exceeded." - "TRANXDONE never got set after the voltage update\n", - __func__, vdd->voltdm.name); - - _post_volt_scale(vdd, target_volt, target_vsel, current_vsel); - - /* - * Disable TransactionDone interrupt , clear all status, clear - * control registers - */ - timeout = 0; - while (timeout++ < VP_TRANXDONE_TIMEOUT) { - vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status, - prm_irqst_ocp_mod_offs, prm_irqst_reg); - if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status)) - break; - udelay(1); - } - - if (timeout >= VP_TRANXDONE_TIMEOUT) - pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying" - "to clear the TRANXDONE status\n", - __func__, vdd->voltdm.name); - - vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); - /* Clear initVDD copy trigger bit */ - vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd; - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - /* Clear force bit */ - vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate; - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - - return 0; -} - -static void __init omap3_vfsm_init(struct omap_vdd_info *vdd) -{ - /* - * Voltage Manager FSM parameters init - * XXX This data should be passed in from the board file - */ - vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET); - vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs, - OMAP3_PRM_VOLTOFFSET_OFFSET); - vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs, - OMAP3_PRM_VOLTSETUP2_OFFSET); -} - -static void __init omap3_vc_init(struct omap_vdd_info *vdd) -{ - static bool is_initialized; - u8 on_vsel, onlp_vsel, ret_vsel, off_vsel; - u32 vc_val; - - if (is_initialized) - return; - - /* Set up the on, inactive, retention and off voltage */ - on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt); - onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt); - ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt); - off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt); - vc_val = ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) | - (onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) | - (ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) | - (off_vsel << vdd->vc_data->vc_common->cmd_off_shift)); - vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg); - - /* - * Generic VC parameters init - * XXX This data should be abstracted out - */ - vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs, - OMAP3_PRM_VC_CH_CONF_OFFSET); - vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs, - OMAP3_PRM_VC_I2C_CFG_OFFSET); - - omap3_vfsm_init(vdd); - - is_initialized = true; -} - - -/* OMAP4 specific voltage init functions */ -static void __init omap4_vc_init(struct omap_vdd_info *vdd) -{ - static bool is_initialized; - u32 vc_val; - - if (is_initialized) - return; - - /* TODO: Configure setup times and CMD_VAL values*/ - - /* - * Generic VC parameters init - * XXX This data should be abstracted out - */ - vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK | - OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK | - OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK); - vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET); - - /* XXX These are magic numbers and do not belong! */ - vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT); - vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET); - - is_initialized = true; -} - -static void __init omap_vc_init(struct omap_vdd_info *vdd) -{ - u32 vc_val; - - if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) { - pr_err("%s: PMIC info requried to configure vc for" - "vdd_%s not populated.Hence cannot initialize vc\n", - __func__, vdd->voltdm.name); - return; - } - - if (!vdd->read_reg || !vdd->write_reg) { - pr_err("%s: No read/write API for accessing vdd_%s regs\n", - __func__, vdd->voltdm.name); - return; - } - - /* Set up the SMPS_SA(i2c slave address in VC */ - vc_val = vdd->read_reg(prm_mod_offs, - vdd->vc_data->vc_common->smps_sa_reg); - vc_val &= ~vdd->vc_data->smps_sa_mask; - vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift; - vdd->write_reg(vc_val, prm_mod_offs, - vdd->vc_data->vc_common->smps_sa_reg); - - /* Setup the VOLRA(pmic reg addr) in VC */ - vc_val = vdd->read_reg(prm_mod_offs, - vdd->vc_data->vc_common->smps_volra_reg); - vc_val &= ~vdd->vc_data->smps_volra_mask; - vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift; - vdd->write_reg(vc_val, prm_mod_offs, - vdd->vc_data->vc_common->smps_volra_reg); - - /* Configure the setup times */ - vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg); - vc_val &= ~vdd->vfsm->voltsetup_mask; - vc_val |= vdd->pmic_info->volt_setup_time << - vdd->vfsm->voltsetup_shift; - vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg); - - if (cpu_is_omap34xx()) - omap3_vc_init(vdd); - else if (cpu_is_omap44xx()) - omap4_vc_init(vdd); -} - -static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd) +static int __init omap_vdd_data_configure(struct voltagedomain *voltdm) { int ret = -EINVAL; - if (!vdd->pmic_info) { + if (!voltdm->pmic) { pr_err("%s: PMIC info requried to configure vdd_%s not" "populated.Hence cannot initialize vdd_%s\n", - __func__, vdd->voltdm.name, vdd->voltdm.name); + __func__, voltdm->name, voltdm->name); goto ovdc_out; } - if (IS_ERR_VALUE(_config_common_vdd_data(vdd))) + if (IS_ERR_VALUE(_config_common_vdd_data(voltdm))) goto ovdc_out; - if (cpu_is_omap34xx()) { - vdd->read_reg = omap3_voltage_read_reg; - vdd->write_reg = omap3_voltage_write_reg; - ret = 0; - } else if (cpu_is_omap44xx()) { - vdd->read_reg = omap4_voltage_read_reg; - vdd->write_reg = omap4_voltage_write_reg; - ret = 0; - } + ret = 0; ovdc_out: return ret; @@ -678,197 +96,65 @@ ovdc_out: */ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) { - struct omap_vdd_info *vdd; - - if (!voltdm || IS_ERR(voltdm)) { - pr_warning("%s: VDD specified does not exist!\n", __func__); - return 0; - } - - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - - return vdd->curr_volt; -} - -/** - * omap_vp_get_curr_volt() - API to get the current vp voltage. - * @voltdm: pointer to the VDD. - * - * This API returns the current voltage for the specified voltage processor - */ -unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm) -{ - struct omap_vdd_info *vdd; - u8 curr_vsel; - if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); return 0; } - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - if (!vdd->read_reg) { - pr_err("%s: No read API for reading vdd_%s regs\n", - __func__, voltdm->name); - return 0; - } - - curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); - - if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) { - pr_warning("%s: PMIC function to convert vsel to voltage" - "in uV not registerd\n", __func__); - return 0; - } - - return vdd->pmic_info->vsel_to_uv(curr_vsel); -} - -/** - * omap_vp_enable() - API to enable a particular VP - * @voltdm: pointer to the VDD whose VP is to be enabled. - * - * This API enables a particular voltage processor. Needed by the smartreflex - * class drivers. - */ -void omap_vp_enable(struct voltagedomain *voltdm) -{ - struct omap_vdd_info *vdd; - u32 vpconfig; - - if (!voltdm || IS_ERR(voltdm)) { - pr_warning("%s: VDD specified does not exist!\n", __func__); - return; - } - - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - if (!vdd->read_reg || !vdd->write_reg) { - pr_err("%s: No read/write API for accessing vdd_%s regs\n", - __func__, voltdm->name); - return; - } - - /* If VP is already enabled, do nothing. Return */ - if (vdd->vp_enabled) - return; - - vp_latch_vsel(vdd); - - /* Enable VP */ - vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); - vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable; - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - vdd->vp_enabled = true; + return voltdm->curr_volt; } /** - * omap_vp_disable() - API to disable a particular VP - * @voltdm: pointer to the VDD whose VP is to be disabled. - * - * This API disables a particular voltage processor. Needed by the smartreflex - * class drivers. - */ -void omap_vp_disable(struct voltagedomain *voltdm) -{ - struct omap_vdd_info *vdd; - u32 vpconfig; - int timeout; - - if (!voltdm || IS_ERR(voltdm)) { - pr_warning("%s: VDD specified does not exist!\n", __func__); - return; - } - - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - if (!vdd->read_reg || !vdd->write_reg) { - pr_err("%s: No read/write API for accessing vdd_%s regs\n", - __func__, voltdm->name); - return; - } - - /* If VP is already disabled, do nothing. Return */ - if (!vdd->vp_enabled) { - pr_warning("%s: Trying to disable VP for vdd_%s when" - "it is already disabled\n", __func__, voltdm->name); - return; - } - - /* Disable VP */ - vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); - vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable; - vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); - - /* - * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us - */ - omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)), - VP_IDLE_TIMEOUT, timeout); - - if (timeout >= VP_IDLE_TIMEOUT) - pr_warning("%s: vdd_%s idle timedout\n", - __func__, voltdm->name); - - vdd->vp_enabled = false; - - return; -} - -/** - * omap_voltage_scale_vdd() - API to scale voltage of a particular - * voltage domain. - * @voltdm: pointer to the VDD which is to be scaled. - * @target_volt: The target voltage of the voltage domain + * voltdm_scale() - API to scale voltage of a particular voltage domain. + * @voltdm: pointer to the voltage domain which is to be scaled. + * @target_volt: The target voltage of the voltage domain * * This API should be called by the kernel to do the voltage scaling - * for a particular voltage domain during dvfs or any other situation. + * for a particular voltage domain during DVFS. */ -int omap_voltage_scale_vdd(struct voltagedomain *voltdm, - unsigned long target_volt) +int voltdm_scale(struct voltagedomain *voltdm, + unsigned long target_volt) { - struct omap_vdd_info *vdd; - if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); return -EINVAL; } - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - - if (!vdd->volt_scale) { + if (!voltdm->scale) { pr_err("%s: No voltage scale API registered for vdd_%s\n", __func__, voltdm->name); return -ENODATA; } - return vdd->volt_scale(vdd, target_volt); + return voltdm->scale(voltdm, target_volt); } /** - * omap_voltage_reset() - Resets the voltage of a particular voltage domain - * to that of the current OPP. - * @voltdm: pointer to the VDD whose voltage is to be reset. + * voltdm_reset() - Resets the voltage of a particular voltage domain + * to that of the current OPP. + * @voltdm: pointer to the voltage domain whose voltage is to be reset. * * This API finds out the correct voltage the voltage domain is supposed * to be at and resets the voltage to that level. Should be used especially * while disabling any voltage compensation modules. */ -void omap_voltage_reset(struct voltagedomain *voltdm) +void voltdm_reset(struct voltagedomain *voltdm) { - unsigned long target_uvdc; + unsigned long target_volt; if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); return; } - target_uvdc = omap_voltage_get_nom_volt(voltdm); - if (!target_uvdc) { + target_volt = omap_voltage_get_nom_volt(voltdm); + if (!target_volt) { pr_err("%s: unable to find current voltage for vdd_%s\n", __func__, voltdm->name); return; } - omap_voltage_scale_vdd(voltdm, target_uvdc); + voltdm_scale(voltdm, target_volt); } /** @@ -893,7 +179,7 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm, return; } - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + vdd = voltdm->vdd; *volt_data = vdd->volt_data; } @@ -924,7 +210,7 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, return ERR_PTR(-EINVAL); } - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + vdd = voltdm->vdd; if (!vdd->volt_data) { pr_warning("%s: voltage table does not exist for vdd_%s\n", @@ -947,54 +233,25 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, * omap_voltage_register_pmic() - API to register PMIC specific data * @voltdm: pointer to the VDD for which the PMIC specific data is * to be registered - * @pmic_info: the structure containing pmic info + * @pmic: the structure containing pmic info * * This API is to be called by the SOC/PMIC file to specify the - * pmic specific info as present in omap_volt_pmic_info structure. + * pmic specific info as present in omap_voltdm_pmic structure. */ int omap_voltage_register_pmic(struct voltagedomain *voltdm, - struct omap_volt_pmic_info *pmic_info) + struct omap_voltdm_pmic *pmic) { - struct omap_vdd_info *vdd; - if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); return -EINVAL; } - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - - vdd->pmic_info = pmic_info; + voltdm->pmic = pmic; return 0; } /** - * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory - * corresponding to a voltage domain. - * - * @voltdm: pointer to the VDD whose debug directory is required. - * - * This API returns pointer to the debugfs directory corresponding - * to the voltage domain. Should be used by drivers requiring to - * add any debug entry for a particular voltage domain. Returns NULL - * in case of error. - */ -struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm) -{ - struct omap_vdd_info *vdd; - - if (!voltdm || IS_ERR(voltdm)) { - pr_warning("%s: VDD specified does not exist!\n", __func__); - return NULL; - } - - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - - return vdd->debug_dir; -} - -/** * omap_change_voltscale_method() - API to change the voltage scaling method. * @voltdm: pointer to the VDD whose voltage scaling method * has to be changed. @@ -1005,23 +262,19 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm) * defined in voltage.h */ void omap_change_voltscale_method(struct voltagedomain *voltdm, - int voltscale_method) + int voltscale_method) { - struct omap_vdd_info *vdd; - if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); return; } - vdd = container_of(voltdm, struct omap_vdd_info, voltdm); - switch (voltscale_method) { case VOLTSCALE_VPFORCEUPDATE: - vdd->volt_scale = vp_forceupdate_scale_voltage; + voltdm->scale = omap_vp_forceupdate_scale; return; case VOLTSCALE_VCBYPASS: - vdd->volt_scale = vc_bypass_scale_voltage; + voltdm->scale = omap_vc_bypass_scale_voltage; return; default: pr_warning("%s: Trying to change the method of voltage scaling" @@ -1029,36 +282,63 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm, } } -/** - * omap_voltage_domain_lookup() - API to get the voltage domain pointer - * @name: Name of the voltage domain - * - * This API looks up in the global vdd_info struct for the - * existence of voltage domain <name>. If it exists, the API returns - * a pointer to the voltage domain structure corresponding to the - * VDD<name>. Else retuns error pointer. - */ -struct voltagedomain *omap_voltage_domain_lookup(char *name) +/* Voltage debugfs support */ +static int vp_volt_debug_get(void *data, u64 *val) { - int i; + struct voltagedomain *voltdm = (struct voltagedomain *)data; - if (!vdd_info) { - pr_err("%s: Voltage driver init not yet happened.Faulting!\n", - __func__); - return ERR_PTR(-EINVAL); + if (!voltdm) { + pr_warning("Wrong paramater passed\n"); + return -EINVAL; + } + *val = omap_vp_get_curr_volt(voltdm); + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n"); + +static int nom_volt_debug_get(void *data, u64 *val) +{ + struct voltagedomain *voltdm = (struct voltagedomain *) data; + + if (!voltdm) { + pr_warning("Wrong paramater passed\n"); + return -EINVAL; } + *val = omap_voltage_get_nom_volt(voltdm); + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL, + "%llu\n"); + +static void __init voltdm_debugfs_init(struct dentry *voltage_dir, + struct voltagedomain *voltdm) +{ + char *name; + + name = kasprintf(GFP_KERNEL, "vdd_%s", voltdm->name); if (!name) { - pr_err("%s: No name to get the votage domain!\n", __func__); - return ERR_PTR(-EINVAL); + pr_warning("%s:vdd_%s: no mem for debugfs\n", __func__, + voltdm->name); + return; } - for (i = 0; i < nr_scalable_vdd; i++) { - if (!(strcmp(name, vdd_info[i]->voltdm.name))) - return &vdd_info[i]->voltdm; + voltdm->debug_dir = debugfs_create_dir(name, voltage_dir); + kfree(name); + if (IS_ERR_OR_NULL(voltdm->debug_dir)) { + pr_warning("%s: Unable to create debugfs directory for" + " vdd_%s\n", __func__, voltdm->name); + voltdm->debug_dir = NULL; + return; } - return ERR_PTR(-EINVAL); + (void) debugfs_create_file("curr_vp_volt", S_IRUGO, voltdm->debug_dir, + (void *) voltdm, &vp_volt_debug_fops); + (void) debugfs_create_file("curr_nominal_volt", S_IRUGO, + voltdm->debug_dir, (void *) voltdm, + &nom_volt_debug_fops); } /** @@ -1070,37 +350,179 @@ struct voltagedomain *omap_voltage_domain_lookup(char *name) */ int __init omap_voltage_late_init(void) { - int i; + struct voltagedomain *voltdm; + struct dentry *voltage_dir; - if (!vdd_info) { + if (list_empty(&voltdm_list)) { pr_err("%s: Voltage driver support not added\n", __func__); return -EINVAL; } voltage_dir = debugfs_create_dir("voltage", NULL); - if (IS_ERR(voltage_dir)) - pr_err("%s: Unable to create voltage debugfs main dir\n", - __func__); - for (i = 0; i < nr_scalable_vdd; i++) { - if (omap_vdd_data_configure(vdd_info[i])) + + list_for_each_entry(voltdm, &voltdm_list, node) { + if (!voltdm->scalable) continue; - omap_vc_init(vdd_info[i]); - vp_init(vdd_info[i]); - vdd_debugfs_init(vdd_info[i]); + + if (voltdm->vdd) { + if (omap_vdd_data_configure(voltdm)) + continue; + omap_vp_init(voltdm); + } + + if (voltdm->vc) + omap_vc_init_channel(voltdm); + + if (voltage_dir) + voltdm_debugfs_init(voltage_dir, voltdm); + } return 0; } -/* XXX document */ -int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod, - struct omap_vdd_info *omap_vdd_array[], - u8 omap_vdd_count) +static struct voltagedomain *_voltdm_lookup(const char *name) { - prm_mod_offs = prm_mod; - prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod; - vdd_info = omap_vdd_array; - nr_scalable_vdd = omap_vdd_count; + struct voltagedomain *voltdm, *temp_voltdm; + + voltdm = NULL; + + list_for_each_entry(temp_voltdm, &voltdm_list, node) { + if (!strcmp(name, temp_voltdm->name)) { + voltdm = temp_voltdm; + break; + } + } + + return voltdm; +} + +/** + * voltdm_add_pwrdm - add a powerdomain to a voltagedomain + * @voltdm: struct voltagedomain * to add the powerdomain to + * @pwrdm: struct powerdomain * to associate with a voltagedomain + * + * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This + * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if + * presented with invalid pointers; -ENOMEM if memory could not be allocated; + * or 0 upon success. + */ +int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm) +{ + if (!voltdm || !pwrdm) + return -EINVAL; + + pr_debug("voltagedomain: associating powerdomain %s with voltagedomain " + "%s\n", pwrdm->name, voltdm->name); + + list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list); + return 0; } + +/** + * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm + * @voltdm: struct voltagedomain * to iterate over + * @fn: callback function * + * + * Call the supplied function @fn for each powerdomain in the + * voltagedomain @voltdm. Returns -EINVAL if presented with invalid + * pointers; or passes along the last return value of the callback + * function, which should be 0 for success or anything else to + * indicate failure. + */ +int voltdm_for_each_pwrdm(struct voltagedomain *voltdm, + int (*fn)(struct voltagedomain *voltdm, + struct powerdomain *pwrdm)) +{ + struct powerdomain *pwrdm; + int ret = 0; + + if (!fn) + return -EINVAL; + + list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node) + ret = (*fn)(voltdm, pwrdm); + + return ret; +} + +/** + * voltdm_for_each - call function on each registered voltagedomain + * @fn: callback function * + * + * Call the supplied function @fn for each registered voltagedomain. + * The callback function @fn can return anything but 0 to bail out + * early from the iterator. Returns the last return value of the + * callback function, which should be 0 for success or anything else + * to indicate failure; or -EINVAL if the function pointer is null. + */ +int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user), + void *user) +{ + struct voltagedomain *temp_voltdm; + int ret = 0; + + if (!fn) + return -EINVAL; + + list_for_each_entry(temp_voltdm, &voltdm_list, node) { + ret = (*fn)(temp_voltdm, user); + if (ret) + break; + } + + return ret; +} + +static int _voltdm_register(struct voltagedomain *voltdm) +{ + if (!voltdm || !voltdm->name) + return -EINVAL; + + INIT_LIST_HEAD(&voltdm->pwrdm_list); + list_add(&voltdm->node, &voltdm_list); + + pr_debug("voltagedomain: registered %s\n", voltdm->name); + + return 0; +} + +/** + * voltdm_lookup - look up a voltagedomain by name, return a pointer + * @name: name of voltagedomain + * + * Find a registered voltagedomain by its name @name. Returns a pointer + * to the struct voltagedomain if found, or NULL otherwise. + */ +struct voltagedomain *voltdm_lookup(const char *name) +{ + struct voltagedomain *voltdm ; + + if (!name) + return NULL; + + voltdm = _voltdm_lookup(name); + + return voltdm; +} + +/** + * voltdm_init - set up the voltagedomain layer + * @voltdm_list: array of struct voltagedomain pointers to register + * + * Loop through the array of voltagedomains @voltdm_list, registering all + * that are available on the current CPU. If voltdm_list is supplied + * and not null, all of the referenced voltagedomains will be + * registered. No return value. + */ +void voltdm_init(struct voltagedomain **voltdms) +{ + struct voltagedomain **v; + + if (voltdms) { + for (v = voltdms; *v; v++) + _voltdm_register(*v); + } +} diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h index e9f5408..c2b4f3b 100644 --- a/arch/arm/mach-omap2/voltage.h +++ b/arch/arm/mach-omap2/voltage.h @@ -19,6 +19,8 @@ #include "vc.h" #include "vp.h" +struct powerdomain; + /* XXX document */ #define VOLTSCALE_VPFORCEUPDATE 1 #define VOLTSCALE_VCBYPASS 2 @@ -31,8 +33,10 @@ #define OMAP3_VOLTOFFSET 0xff #define OMAP3_VOLTSETUP2 0xff +struct omap_vdd_info; + /** - * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield + * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield * data * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base @@ -42,7 +46,7 @@ * XXX It is not necessary to have both a _mask and a _shift for the same * bitfield - remove one! */ -struct omap_vfsm_instance_data { +struct omap_vfsm_instance { u32 voltsetup_mask; u8 voltsetup_reg; u8 voltsetup_shift; @@ -50,11 +54,41 @@ struct omap_vfsm_instance_data { /** * struct voltagedomain - omap voltage domain global structure. - * @name: Name of the voltage domain which can be used as a unique - * identifier. + * @name: Name of the voltage domain which can be used as a unique identifier. + * @scalable: Whether or not this voltage domain is scalable + * @node: list_head linking all voltage domains + * @pwrdm_node: list_head linking all powerdomains in this voltagedomain + * @vdd: to be removed + * @pwrdms: powerdomains in this voltagedomain + * @scale: function used to scale the voltage of the voltagedomain + * @curr_volt: current nominal voltage for this voltage domain */ struct voltagedomain { char *name; + bool scalable; + struct list_head node; + struct list_head pwrdm_list; + struct omap_vc_channel *vc; + const struct omap_vfsm_instance *vfsm; + struct omap_vp_instance *vp; + struct omap_voltdm_pmic *pmic; + + /* VC/VP register access functions: SoC specific */ + u32 (*read) (u8 offset); + void (*write) (u32 val, u8 offset); + u32 (*rmw)(u32 mask, u32 bits, u8 offset); + + union { + const char *name; + u32 rate; + } sys_clk; + + int (*scale) (struct voltagedomain *voltdm, + unsigned long target_volt); + u32 curr_volt; + + struct omap_vdd_info *vdd; + struct dentry *debug_dir; }; /** @@ -76,14 +110,52 @@ struct omap_volt_data { u8 vp_errgain; }; +/* + * Introduced in OMAP4, is a concept of a default channel - in OMAP4, this + * channel is MPU, all other domains such as IVA/CORE, could optionally + * link their i2c reg configuration to use MPU channel's configuration if + * required. To do this, mark in the PMIC structure's + * i2c_slave_addr, volt_reg_addr,cmd_reg_addr with this macro. + */ +#define USE_DEFAULT_CHANNEL_I2C_PARAM 0x8000 + +/* Min and max voltages from OMAP perspective */ +#define OMAP3430_VP1_VLIMITTO_VDDMIN 850000 +#define OMAP3430_VP1_VLIMITTO_VDDMAX 1425000 +#define OMAP3430_VP2_VLIMITTO_VDDMIN 900000 +#define OMAP3430_VP2_VLIMITTO_VDDMAX 1150000 + +#define OMAP3630_VP1_VLIMITTO_VDDMIN 900000 +#define OMAP3630_VP1_VLIMITTO_VDDMAX 1350000 +#define OMAP3630_VP2_VLIMITTO_VDDMIN 900000 +#define OMAP3630_VP2_VLIMITTO_VDDMAX 1200000 + +#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 830000 +#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 1410000 +#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 830000 +#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 1260000 +#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 830000 +#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 1200000 + +#define OMAP4_VP_CONFIG_ERROROFFSET 0x00 +#define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01 +#define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04 +#define OMAP4_VP_VLIMITTO_TIMEOUT_US 200 + /** - * struct omap_volt_pmic_info - PMIC specific data required by voltage driver. + * struct omap_voltdm_pmic - PMIC specific data required by voltage driver. * @slew_rate: PMIC slew rate (in uv/us) * @step_size: PMIC voltage step size (in uv) + * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC + * @i2c_mcode: master code value for I2C high-speed preamble transmission * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV. * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value. + * @i2c_hscll_low: PMIC interface speed config for highspeed mode (T low) + * @i2c_hscll_high: PMIC interface speed config for highspeed mode (T high) + * @i2c_scll_low: PMIC interface speed config for fullspeed mode (T low) + * @i2c_scll_high: PMIC interface speed config for fullspeed mode (T high) */ -struct omap_volt_pmic_info { +struct omap_voltdm_pmic { int slew_rate; int step_size; u32 on_volt; @@ -94,78 +166,78 @@ struct omap_volt_pmic_info { u8 vp_erroroffset; u8 vp_vstepmin; u8 vp_vstepmax; - u8 vp_vddmin; - u8 vp_vddmax; + u32 vp_vddmin; + u32 vp_vddmax; u8 vp_timeout_us; - u8 i2c_slave_addr; - u8 pmic_reg; + u16 i2c_slave_addr; + u16 volt_reg_addr; + u16 cmd_reg_addr; + bool i2c_high_speed; + u8 i2c_hscll_low; + u8 i2c_hscll_high; + u8 i2c_scll_low; + u8 i2c_scll_high; + u8 i2c_mcode; unsigned long (*vsel_to_uv) (const u8 vsel); u8 (*uv_to_vsel) (unsigned long uV); }; /** + * struct omap_vdd_dep_volt - Map table for voltage dependencies + * @main_vdd_volt : The main vdd voltage + * @dep_vdd_volt : The voltage at which the dependent vdd should be + * when the main vdd is at <main_vdd_volt> voltage + * + * Table containing the parent vdd voltage and the dependent vdd voltage + * corresponding to it. + */ +struct omap_vdd_dep_volt { + u32 main_vdd_volt; + u32 dep_vdd_volt; +}; + +/** + * struct omap_vdd_dep_info - Dependent vdd info + * @name : Dependent vdd name + * @_dep_voltdm : internal structure meant to prevent multiple lookups + * @dep_table : Table containing the dependent vdd voltage + * corresponding to every main vdd voltage. + * @nr_dep_entries : number of dependency voltage entries + */ +struct omap_vdd_dep_info { + char *name; + struct voltagedomain *_dep_voltdm; + struct omap_vdd_dep_volt *dep_table; + int nr_dep_entries; +}; + +/** * omap_vdd_info - Per Voltage Domain info * * @volt_data : voltage table having the distinct voltages supported * by the domain and other associated per voltage data. - * @pmic_info : pmic specific parameters which should be populted by - * the pmic drivers. - * @vp_data : the register values, shifts, masks for various - * vp registers - * @vp_rt_data : VP data derived at runtime, not predefined - * @vc_data : structure containing various various vc registers, - * shifts, masks etc. - * @vfsm : voltage manager FSM data - * @voltdm : pointer to the voltage domain structure - * @debug_dir : debug directory for this voltage domain. - * @curr_volt : current voltage for this vdd. - * @vp_enabled : flag to keep track of whether vp is enabled or not - * @volt_scale : API to scale the voltage of the vdd. + * @dep_vdd_info : Array ending with a 0 terminator for dependency + * voltage information. */ struct omap_vdd_info { struct omap_volt_data *volt_data; - struct omap_volt_pmic_info *pmic_info; - struct omap_vp_instance_data *vp_data; - struct omap_vp_runtime_data vp_rt_data; - struct omap_vc_instance_data *vc_data; - const struct omap_vfsm_instance_data *vfsm; - struct voltagedomain voltdm; - struct dentry *debug_dir; - u32 curr_volt; - bool vp_enabled; - u32 (*read_reg) (u16 mod, u8 offset); - void (*write_reg) (u32 val, u16 mod, u8 offset); - int (*volt_scale) (struct omap_vdd_info *vdd, - unsigned long target_volt); + struct omap_vdd_dep_info *dep_vdd_info; }; -unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm); -void omap_vp_enable(struct voltagedomain *voltdm); -void omap_vp_disable(struct voltagedomain *voltdm); -int omap_voltage_scale_vdd(struct voltagedomain *voltdm, - unsigned long target_volt); -void omap_voltage_reset(struct voltagedomain *voltdm); void omap_voltage_get_volttable(struct voltagedomain *voltdm, struct omap_volt_data **volt_data); struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, unsigned long volt); unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm); -struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm); -int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod, - struct omap_vdd_info *omap_vdd_array[], - u8 omap_vdd_count); #ifdef CONFIG_PM int omap_voltage_register_pmic(struct voltagedomain *voltdm, - struct omap_volt_pmic_info *pmic_info); + struct omap_voltdm_pmic *pmic); void omap_change_voltscale_method(struct voltagedomain *voltdm, int voltscale_method); -/* API to get the voltagedomain pointer */ -struct voltagedomain *omap_voltage_domain_lookup(char *name); - int omap_voltage_late_init(void); #else static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm, - struct omap_volt_pmic_info *pmic_info) + struct omap_voltdm_pmic *pmic) { return -EINVAL; } @@ -175,10 +247,20 @@ static inline int omap_voltage_late_init(void) { return -EINVAL; } -static inline struct voltagedomain *omap_voltage_domain_lookup(char *name) -{ - return ERR_PTR(-EINVAL); -} #endif +extern void omap2xxx_voltagedomains_init(void); +extern void omap3xxx_voltagedomains_init(void); +extern void omap44xx_voltagedomains_init(void); + +struct voltagedomain *voltdm_lookup(const char *name); +void voltdm_init(struct voltagedomain **voltdm_list); +int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm); +int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user), + void *user); +int voltdm_for_each_pwrdm(struct voltagedomain *voltdm, + int (*fn)(struct voltagedomain *voltdm, + struct powerdomain *pwrdm)); +int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt); +void voltdm_reset(struct voltagedomain *voltdm); #endif diff --git a/arch/arm/mach-omap2/voltagedomains2xxx_data.c b/arch/arm/mach-omap2/voltagedomains2xxx_data.c new file mode 100644 index 0000000..69ff261 --- /dev/null +++ b/arch/arm/mach-omap2/voltagedomains2xxx_data.c @@ -0,0 +1,32 @@ +/* + * OMAP3 voltage domain data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + + * 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 "voltage.h" + +static struct voltagedomain omap2_voltdm_core = { + .name = "core", +}; + +static struct voltagedomain omap2_voltdm_wkup = { + .name = "wakeup", +}; + +static struct voltagedomain *voltagedomains_omap2[] __initdata = { + &omap2_voltdm_core, + &omap2_voltdm_wkup, + NULL, +}; + +void __init omap2xxx_voltagedomains_init(void) +{ + voltdm_init(voltagedomains_omap2); +} diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c index def230f..8264d15 100644 --- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c +++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c @@ -31,50 +31,63 @@ * VDD data */ -static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = { +static const struct omap_vfsm_instance omap3_vdd1_vfsm = { .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, .voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT, .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK, }; -static struct omap_vdd_info omap3_vdd1_info = { - .vp_data = &omap3_vp1_data, - .vc_data = &omap3_vc1_data, - .vfsm = &omap3_vdd1_vfsm_data, - .voltdm = { - .name = "mpu", - }, -}; +static struct omap_vdd_info omap3_vdd1_info; -static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = { +static const struct omap_vfsm_instance omap3_vdd2_vfsm = { .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, .voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT, .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK, }; -static struct omap_vdd_info omap3_vdd2_info = { - .vp_data = &omap3_vp2_data, - .vc_data = &omap3_vc2_data, - .vfsm = &omap3_vdd2_vfsm_data, - .voltdm = { - .name = "core", - }, +static struct omap_vdd_info omap3_vdd2_info; + +static struct voltagedomain omap3_voltdm_mpu = { + .name = "mpu_iva", + .scalable = true, + .read = omap3_prm_vcvp_read, + .write = omap3_prm_vcvp_write, + .rmw = omap3_prm_vcvp_rmw, + .vc = &omap3_vc_mpu, + .vfsm = &omap3_vdd1_vfsm, + .vp = &omap3_vp_mpu, + .vdd = &omap3_vdd1_info, }; -/* OMAP3 VDD structures */ -static struct omap_vdd_info *omap3_vdd_info[] = { - &omap3_vdd1_info, - &omap3_vdd2_info, +static struct voltagedomain omap3_voltdm_core = { + .name = "core", + .scalable = true, + .read = omap3_prm_vcvp_read, + .write = omap3_prm_vcvp_write, + .rmw = omap3_prm_vcvp_rmw, + .vc = &omap3_vc_core, + .vfsm = &omap3_vdd2_vfsm, + .vp = &omap3_vp_core, + .vdd = &omap3_vdd2_info, }; -/* OMAP3 specific voltage init functions */ -static int __init omap3xxx_voltage_early_init(void) -{ - s16 prm_mod = OMAP3430_GR_MOD; - s16 prm_irqst_ocp_mod = OCP_MOD; +static struct voltagedomain omap3_voltdm_wkup = { + .name = "wakeup", +}; + +static struct voltagedomain *voltagedomains_omap3[] __initdata = { + &omap3_voltdm_mpu, + &omap3_voltdm_core, + &omap3_voltdm_wkup, + NULL, +}; + +static const char *sys_clk_name __initdata = "sys_ck"; - if (!cpu_is_omap34xx()) - return 0; +void __init omap3xxx_voltagedomains_init(void) +{ + struct voltagedomain *voltdm; + int i; /* * XXX Will depend on the process, validation, and binning @@ -83,13 +96,16 @@ static int __init omap3xxx_voltage_early_init(void) if (cpu_is_omap3630()) { omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data; omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data; + omap3_vdd1_info.dep_vdd_info = omap36xx_vddmpu_dep_info; + } else { omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data; omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data; + omap3_vdd1_info.dep_vdd_info = omap34xx_vddmpu_dep_info; } - return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod, - omap3_vdd_info, - ARRAY_SIZE(omap3_vdd_info)); + for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++) + voltdm->sys_clk.name = sys_clk_name; + + voltdm_init(voltagedomains_omap3); }; -core_initcall(omap3xxx_voltage_early_init); diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c index cb64996..5fce5ad 100644 --- a/arch/arm/mach-omap2/voltagedomains44xx_data.c +++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c @@ -20,6 +20,7 @@ #include <linux/kernel.h> #include <linux/err.h> #include <linux/init.h> +#include <linux/clk.h> #include <plat/common.h> @@ -32,71 +33,101 @@ #include "vc.h" #include "vp.h" -static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = { +static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = { .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET, }; -static struct omap_vdd_info omap4_vdd_mpu_info = { - .vp_data = &omap4_vp_mpu_data, - .vc_data = &omap4_vc_mpu_data, - .vfsm = &omap4_vdd_mpu_vfsm_data, - .voltdm = { - .name = "mpu", - }, -}; +static struct omap_vdd_info omap4_vdd_mpu_info; -static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = { +static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = { .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET, }; -static struct omap_vdd_info omap4_vdd_iva_info = { - .vp_data = &omap4_vp_iva_data, - .vc_data = &omap4_vc_iva_data, - .vfsm = &omap4_vdd_iva_vfsm_data, - .voltdm = { - .name = "iva", - }, -}; +static struct omap_vdd_info omap4_vdd_iva_info; -static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = { +static const struct omap_vfsm_instance omap4_vdd_core_vfsm = { .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET, }; -static struct omap_vdd_info omap4_vdd_core_info = { - .vp_data = &omap4_vp_core_data, - .vc_data = &omap4_vc_core_data, - .vfsm = &omap4_vdd_core_vfsm_data, - .voltdm = { - .name = "core", - }, +static struct omap_vdd_info omap4_vdd_core_info; + +static struct voltagedomain omap4_voltdm_mpu = { + .name = "mpu", + .scalable = true, + .read = omap4_prm_vcvp_read, + .write = omap4_prm_vcvp_write, + .rmw = omap4_prm_vcvp_rmw, + .vc = &omap4_vc_mpu, + .vfsm = &omap4_vdd_mpu_vfsm, + .vp = &omap4_vp_mpu, + .vdd = &omap4_vdd_mpu_info, +}; + +static struct voltagedomain omap4_voltdm_iva = { + .name = "iva", + .scalable = true, + .read = omap4_prm_vcvp_read, + .write = omap4_prm_vcvp_write, + .rmw = omap4_prm_vcvp_rmw, + .vc = &omap4_vc_iva, + .vfsm = &omap4_vdd_iva_vfsm, + .vp = &omap4_vp_iva, + .vdd = &omap4_vdd_iva_info, }; -/* OMAP4 VDD structures */ -static struct omap_vdd_info *omap4_vdd_info[] = { - &omap4_vdd_mpu_info, - &omap4_vdd_iva_info, - &omap4_vdd_core_info, +static struct voltagedomain omap4_voltdm_core = { + .name = "core", + .scalable = true, + .read = omap4_prm_vcvp_read, + .write = omap4_prm_vcvp_write, + .rmw = omap4_prm_vcvp_rmw, + .vc = &omap4_vc_core, + .vfsm = &omap4_vdd_core_vfsm, + .vp = &omap4_vp_core, + .vdd = &omap4_vdd_core_info, }; -/* OMAP4 specific voltage init functions */ -static int __init omap44xx_voltage_early_init(void) -{ - s16 prm_mod = OMAP4430_PRM_DEVICE_INST; - s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST; +static struct voltagedomain omap4_voltdm_wkup = { + .name = "wakeup", +}; + +static struct voltagedomain *voltagedomains_omap4[] __initdata = { + &omap4_voltdm_mpu, + &omap4_voltdm_iva, + &omap4_voltdm_core, + &omap4_voltdm_wkup, + NULL, +}; - if (!cpu_is_omap44xx()) - return 0; +static const char *sys_clk_name __initdata = "sys_clkin_ck"; + +void __init omap44xx_voltagedomains_init(void) +{ + struct voltagedomain *voltdm; + int i; /* * XXX Will depend on the process, validation, and binning * for the currently-running IC */ - omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data; - omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data; - omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data; + if (cpu_is_omap443x()) { + omap4_vdd_mpu_info.volt_data = omap443x_vdd_mpu_volt_data; + omap4_vdd_iva_info.volt_data = omap443x_vdd_iva_volt_data; + omap4_vdd_core_info.volt_data = omap443x_vdd_core_volt_data; + omap4_vdd_mpu_info.dep_vdd_info = omap443x_vddmpu_dep_info; + omap4_vdd_iva_info.dep_vdd_info = omap443x_vddiva_dep_info; + } else if (cpu_is_omap446x()) { + omap4_vdd_mpu_info.volt_data = omap446x_vdd_mpu_volt_data; + omap4_vdd_iva_info.volt_data = omap446x_vdd_iva_volt_data; + omap4_vdd_core_info.volt_data = omap446x_vdd_core_volt_data; + omap4_vdd_mpu_info.dep_vdd_info = omap446x_vddmpu_dep_info; + omap4_vdd_iva_info.dep_vdd_info = omap446x_vddiva_dep_info; + } else { + return; + } + + for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++) + voltdm->sys_clk.name = sys_clk_name; - return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod, - omap4_vdd_info, - ARRAY_SIZE(omap4_vdd_info)); + voltdm_init(voltagedomains_omap4); }; -core_initcall(omap44xx_voltage_early_init); diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c new file mode 100644 index 0000000..4677921 --- /dev/null +++ b/arch/arm/mach-omap2/vp.c @@ -0,0 +1,329 @@ +#include <linux/kernel.h> +#include <linux/init.h> + +#include <plat/common.h> + +#include "voltage.h" +#include "vp.h" +#include "prm-regbits-34xx.h" +#include "prm-regbits-44xx.h" +#include "prm44xx.h" + +static void vp_latch_vsel(struct voltagedomain *voltdm) +{ + struct omap_vp_instance *vp = voltdm->vp; + u32 vpconfig; + unsigned long uvdc; + char vsel; + + uvdc = omap_voltage_get_nom_volt(voltdm); + if (!uvdc) { + pr_warning("%s: unable to find current voltage for vdd_%s\n", + __func__, voltdm->name); + return; + } + + if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { + pr_warning("%s: PMIC function to convert voltage in uV to" + " vsel not registered\n", __func__); + return; + } + + vsel = voltdm->pmic->uv_to_vsel(uvdc); + + vpconfig = voltdm->read(vp->vpconfig); + vpconfig &= ~(vp->common->vpconfig_initvoltage_mask | + vp->common->vpconfig_initvdd); + vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask); + voltdm->write(vpconfig, vp->vpconfig); + + /* Trigger initVDD value copy to voltage processor */ + voltdm->write((vpconfig | vp->common->vpconfig_initvdd), + vp->vpconfig); + + /* Clear initVDD copy trigger bit */ + voltdm->write(vpconfig, vp->vpconfig); +} + +/* Generic voltage init functions */ +void __init omap_vp_init(struct voltagedomain *voltdm) +{ + struct omap_vp_instance *vp = voltdm->vp; + u32 val, sys_clk_rate, timeout, waittime; + u32 vddmin, vddmax, vstepmin, vstepmax; + + if (!voltdm->read || !voltdm->write) { + pr_err("%s: No read/write API for accessing vdd_%s regs\n", + __func__, voltdm->name); + return; + } + + vp->enabled = false; + + /* Divide to avoid overflow */ + sys_clk_rate = voltdm->sys_clk.rate / 1000; + + timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000; + vddmin = voltdm->pmic->uv_to_vsel(voltdm->pmic->vp_vddmin); + vddmax = voltdm->pmic->uv_to_vsel(voltdm->pmic->vp_vddmax); + + waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) * + sys_clk_rate) / 1000; + vstepmin = voltdm->pmic->vp_vstepmin; + vstepmax = voltdm->pmic->vp_vstepmax; + + /* + * VP_CONFIG: error gain is not set here, it will be updated + * on each scale, based on OPP. + */ + val = (voltdm->pmic->vp_erroroffset << + __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) | + vp->common->vpconfig_timeouten; + voltdm->write(val, vp->vpconfig); + + /* VSTEPMIN */ + val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) | + (vstepmin << vp->common->vstepmin_stepmin_shift); + voltdm->write(val, vp->vstepmin); + + /* VSTEPMAX */ + val = (vstepmax << vp->common->vstepmax_stepmax_shift) | + (waittime << vp->common->vstepmax_smpswaittimemax_shift); + voltdm->write(val, vp->vstepmax); + + /* VLIMITTO */ + val = (vddmax << vp->common->vlimitto_vddmax_shift) | + (vddmin << vp->common->vlimitto_vddmin_shift) | + (timeout << vp->common->vlimitto_timeout_shift); + voltdm->write(val, vp->vlimitto); +} + +int omap_vp_update_errorgain(struct voltagedomain *voltdm, + unsigned long target_volt) +{ + struct omap_volt_data *volt_data; + + /* Get volt_data corresponding to target_volt */ + volt_data = omap_voltage_get_voltdata(voltdm, target_volt); + if (IS_ERR(volt_data)) + return -EINVAL; + + /* Setting vp errorgain based on the voltage */ + voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask, + volt_data->vp_errgain << + __ffs(voltdm->vp->common->vpconfig_errorgain_mask), + voltdm->vp->vpconfig); + + return 0; +} + +/* VP force update method of voltage scaling */ +int omap_vp_forceupdate_scale(struct voltagedomain *voltdm, + unsigned long target_volt) +{ + struct omap_vp_instance *vp = voltdm->vp; + u32 vpconfig; + u8 target_vsel, current_vsel; + int ret, timeout = 0; + + ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, ¤t_vsel); + if (ret) + return ret; + + /* + * Clear all pending TransactionDone interrupt/status. Typical latency + * is <3us + */ + while (timeout++ < VP_TRANXDONE_TIMEOUT) { + vp->common->ops->clear_txdone(vp->id); + if (!vp->common->ops->check_txdone(vp->id)) + break; + udelay(1); + } + if (timeout >= VP_TRANXDONE_TIMEOUT) { + pr_warning("%s: vdd_%s TRANXDONE timeout exceeded." + "Voltage change aborted", __func__, voltdm->name); + return -ETIMEDOUT; + } + + /* Configure for VP-Force Update */ + vpconfig = voltdm->read(vp->vpconfig); + vpconfig &= ~(vp->common->vpconfig_initvdd | + vp->common->vpconfig_forceupdate | + vp->common->vpconfig_initvoltage_mask); + vpconfig |= ((target_vsel << + __ffs(vp->common->vpconfig_initvoltage_mask))); + voltdm->write(vpconfig, vp->vpconfig); + + /* Trigger initVDD value copy to voltage processor */ + vpconfig |= vp->common->vpconfig_initvdd; + voltdm->write(vpconfig, vp->vpconfig); + + /* Force update of voltage */ + vpconfig |= vp->common->vpconfig_forceupdate; + voltdm->write(vpconfig, vp->vpconfig); + + /* + * Wait for TransactionDone. Typical latency is <200us. + * Depends on SMPSWAITTIMEMIN/MAX and voltage change + */ + timeout = 0; + omap_test_timeout(vp->common->ops->check_txdone(vp->id), + VP_TRANXDONE_TIMEOUT, timeout); + if (timeout >= VP_TRANXDONE_TIMEOUT) + pr_err("%s: vdd_%s TRANXDONE timeout exceeded." + "TRANXDONE never got set after the voltage update\n", + __func__, voltdm->name); + + omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel); + + /* + * Disable TransactionDone interrupt , clear all status, clear + * control registers + */ + timeout = 0; + while (timeout++ < VP_TRANXDONE_TIMEOUT) { + vp->common->ops->clear_txdone(vp->id); + if (!vp->common->ops->check_txdone(vp->id)) + break; + udelay(1); + } + + if (timeout >= VP_TRANXDONE_TIMEOUT) + pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying" + "to clear the TRANXDONE status\n", + __func__, voltdm->name); + + vpconfig = voltdm->read(vp->vpconfig); + /* Clear initVDD copy trigger bit */ + vpconfig &= ~vp->common->vpconfig_initvdd; + voltdm->write(vpconfig, vp->vpconfig); + /* Clear force bit */ + vpconfig &= ~vp->common->vpconfig_forceupdate; + voltdm->write(vpconfig, vp->vpconfig); + + return 0; +} + +/** + * omap_vp_get_curr_volt() - API to get the current vp voltage. + * @voltdm: pointer to the VDD. + * + * This API returns the current voltage for the specified voltage processor + */ +unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm) +{ + struct omap_vp_instance *vp = voltdm->vp; + u8 curr_vsel; + + if (!voltdm || IS_ERR(voltdm)) { + pr_warning("%s: VDD specified does not exist!\n", __func__); + return 0; + } + + if (!voltdm->read) { + pr_err("%s: No read API for reading vdd_%s regs\n", + __func__, voltdm->name); + return 0; + } + + curr_vsel = (voltdm->read(vp->voltage) & vp->common->vpvoltage_mask) + >> __ffs(vp->common->vpvoltage_mask); + + if (!voltdm->pmic || !voltdm->pmic->vsel_to_uv) { + pr_warning("%s: PMIC function to convert vsel to voltage" + "in uV not registerd\n", __func__); + return 0; + } + + return voltdm->pmic->vsel_to_uv(curr_vsel); +} + +/** + * omap_vp_enable() - API to enable a particular VP + * @voltdm: pointer to the VDD whose VP is to be enabled. + * + * This API enables a particular voltage processor. Needed by the smartreflex + * class drivers. + */ +void omap_vp_enable(struct voltagedomain *voltdm) +{ + struct omap_vp_instance *vp; + u32 vpconfig; + + if (!voltdm || IS_ERR(voltdm)) { + pr_warning("%s: VDD specified does not exist!\n", __func__); + return; + } + + vp = voltdm->vp; + if (!voltdm->read || !voltdm->write) { + pr_err("%s: No read/write API for accessing vdd_%s regs\n", + __func__, voltdm->name); + return; + } + + /* If VP is already enabled, do nothing. Return */ + if (vp->enabled) + return; + + vp_latch_vsel(voltdm); + + /* Enable VP */ + vpconfig = voltdm->read(vp->vpconfig); + vpconfig |= vp->common->vpconfig_vpenable; + voltdm->write(vpconfig, vp->vpconfig); + vp->enabled = true; +} + +/** + * omap_vp_disable() - API to disable a particular VP + * @voltdm: pointer to the VDD whose VP is to be disabled. + * + * This API disables a particular voltage processor. Needed by the smartreflex + * class drivers. + */ +void omap_vp_disable(struct voltagedomain *voltdm) +{ + struct omap_vp_instance *vp; + u32 vpconfig; + int timeout; + + if (!voltdm || IS_ERR(voltdm)) { + pr_warning("%s: VDD specified does not exist!\n", __func__); + return; + } + + vp = voltdm->vp; + if (!voltdm->read || !voltdm->write) { + pr_err("%s: No read/write API for accessing vdd_%s regs\n", + __func__, voltdm->name); + return; + } + + /* If VP is already disabled, do nothing. Return */ + if (!vp->enabled) { + pr_warning("%s: Trying to disable VP for vdd_%s when" + "it is already disabled\n", __func__, voltdm->name); + return; + } + + /* Disable VP */ + vpconfig = voltdm->read(vp->vpconfig); + vpconfig &= ~vp->common->vpconfig_vpenable; + voltdm->write(vpconfig, vp->vpconfig); + + /* + * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us + */ + omap_test_timeout((voltdm->read(vp->vstatus)), + VP_IDLE_TIMEOUT, timeout); + + if (timeout >= VP_IDLE_TIMEOUT) + pr_warning("%s: vdd_%s idle timedout\n", + __func__, voltdm->name); + + vp->enabled = false; + + return; +} diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h index 7ce134f..f78752b 100644 --- a/arch/arm/mach-omap2/vp.h +++ b/arch/arm/mach-omap2/vp.h @@ -19,44 +19,60 @@ #include <linux/kernel.h> +struct voltagedomain; + +/* + * Voltage Processor (VP) identifiers + */ +#define OMAP3_VP_VDD_MPU_ID 0 +#define OMAP3_VP_VDD_CORE_ID 1 +#define OMAP4_VP_VDD_CORE_ID 0 +#define OMAP4_VP_VDD_IVA_ID 1 +#define OMAP4_VP_VDD_MPU_ID 2 + /* XXX document */ #define VP_IDLE_TIMEOUT 200 #define VP_TRANXDONE_TIMEOUT 300 +/** + * struct omap_vp_ops - per-VP operations + * @check_txdone: check for VP transaction done + * @clear_txdone: clear VP transaction done status + */ +struct omap_vp_ops { + u32 (*check_txdone)(u8 vp_id); + void (*clear_txdone)(u8 vp_id); +}; /** - * struct omap_vp_common_data - register data common to all VDDs + * struct omap_vp_common - register data common to all VDDs + * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg - * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg - * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg - * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg - * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg - * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg - * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg - * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg - * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg - * - * XXX It it not necessary to have both a mask and a shift for the same - * bitfield - remove one - * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix! + * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg + * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg + * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg + * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg + * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg + * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg + * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg + * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg */ -struct omap_vp_common_data { +struct omap_vp_common { + u32 vpconfig_erroroffset_mask; u32 vpconfig_errorgain_mask; u32 vpconfig_initvoltage_mask; - u32 vpconfig_timeouten; - u32 vpconfig_initvdd; - u32 vpconfig_forceupdate; - u32 vpconfig_vpenable; - u8 vpconfig_erroroffset_shift; - u8 vpconfig_errorgain_shift; - u8 vpconfig_initvoltage_shift; + u8 vpconfig_timeouten; + u8 vpconfig_initvdd; + u8 vpconfig_forceupdate; + u8 vpconfig_vpenable; u8 vstepmin_stepmin_shift; u8 vstepmin_smpswaittimemin_shift; u8 vstepmax_stepmax_shift; @@ -64,80 +80,49 @@ struct omap_vp_common_data { u8 vlimitto_vddmin_shift; u8 vlimitto_vddmax_shift; u8 vlimitto_timeout_shift; -}; + u8 vpvoltage_mask; -/** - * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data - * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM - * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg - * - * XXX prm_irqst_reg does not belong here - * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a - * hardware bug - * XXX This structure is probably not needed - */ -struct omap_vp_prm_irqst_data { - u8 prm_irqst_reg; - u32 tranxdone_status; + const struct omap_vp_ops *ops; }; /** - * struct omap_vp_instance_data - VP register offsets (per-VDD) - * @vp_common: pointer to struct omap_vp_common_data * for this SoC - * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD + * struct omap_vp_instance - VP register offsets (per-VDD) + * @common: pointer to struct omap_vp_common * for this SoC * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start + * @enabled: flag to keep track of whether vp is enabled or not * * XXX vp_common is probably not needed since it is per-SoC */ -struct omap_vp_instance_data { - const struct omap_vp_common_data *vp_common; - const struct omap_vp_prm_irqst_data *prm_irqst_data; +struct omap_vp_instance { + const struct omap_vp_common *common; u8 vpconfig; u8 vstepmin; u8 vstepmax; u8 vlimitto; u8 vstatus; u8 voltage; + u8 id; + bool enabled; }; -/** - * struct omap_vp_runtime_data - VP data populated at runtime by code - * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG - * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG - * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN - * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX - * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO - * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN - * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX - * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO - * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO - * - * XXX Is this structure really needed? Why not just program the - * device directly? They are in PRM space, therefore in the WKUP - * powerdomain, so register contents should not be lost in off-mode. - * XXX Some of these fields are incorrectly named, e.g., vstep* - */ -struct omap_vp_runtime_data { - u32 vpconfig_erroroffset; - u16 vpconfig_errorgain; - u16 vstepmin_smpswaittimemin; - u16 vstepmax_smpswaittimemax; - u16 vlimitto_timeout; - u8 vstepmin_stepmin; - u8 vstepmax_stepmax; - u8 vlimitto_vddmin; - u8 vlimitto_vddmax; -}; +extern struct omap_vp_instance omap3_vp_mpu; +extern struct omap_vp_instance omap3_vp_core; -extern struct omap_vp_instance_data omap3_vp1_data; -extern struct omap_vp_instance_data omap3_vp2_data; +extern struct omap_vp_instance omap4_vp_mpu; +extern struct omap_vp_instance omap4_vp_iva; +extern struct omap_vp_instance omap4_vp_core; -extern struct omap_vp_instance_data omap4_vp_mpu_data; -extern struct omap_vp_instance_data omap4_vp_iva_data; -extern struct omap_vp_instance_data omap4_vp_core_data; +void omap_vp_init(struct voltagedomain *voltdm); +void omap_vp_enable(struct voltagedomain *voltdm); +void omap_vp_disable(struct voltagedomain *voltdm); +unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm); +int omap_vp_forceupdate_scale(struct voltagedomain *voltdm, + unsigned long target_volt); +int omap_vp_update_errorgain(struct voltagedomain *voltdm, + unsigned long target_volt); #endif diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c index 6452170..260c554 100644 --- a/arch/arm/mach-omap2/vp3xxx_data.c +++ b/arch/arm/mach-omap2/vp3xxx_data.c @@ -25,16 +25,20 @@ #include "voltage.h" #include "vp.h" +#include "prm2xxx_3xxx.h" + +static const struct omap_vp_ops omap3_vp_ops = { + .check_txdone = omap3_prm_vp_check_txdone, + .clear_txdone = omap3_prm_vp_clear_txdone, +}; /* * VP data common to 34xx/36xx chips * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file. */ -static const struct omap_vp_common_data omap3_vp_common = { - .vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT, +static const struct omap_vp_common omap3_vp_common = { + .vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK, .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK, - .vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT, - .vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT, .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK, .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK, .vpconfig_initvdd = OMAP3430_INITVDD_MASK, @@ -47,36 +51,29 @@ static const struct omap_vp_common_data omap3_vp_common = { .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT, .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT, .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT, -}; + .vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK, -static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = { - .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET, - .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK, + .ops = &omap3_vp_ops, }; -struct omap_vp_instance_data omap3_vp1_data = { - .vp_common = &omap3_vp_common, +struct omap_vp_instance omap3_vp_mpu = { + .id = OMAP3_VP_VDD_MPU_ID, + .common = &omap3_vp_common, .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET, .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET, .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET, .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET, .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET, .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET, - .prm_irqst_data = &omap3_vp1_prm_irqst_data, -}; - -static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = { - .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET, - .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK, }; -struct omap_vp_instance_data omap3_vp2_data = { - .vp_common = &omap3_vp_common, +struct omap_vp_instance omap3_vp_core = { + .id = OMAP3_VP_VDD_CORE_ID, + .common = &omap3_vp_common, .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET, .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET, .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET, .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET, .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET, .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET, - .prm_irqst_data = &omap3_vp2_prm_irqst_data, }; diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c index 65d1ad6..b4e7704 100644 --- a/arch/arm/mach-omap2/vp44xx_data.c +++ b/arch/arm/mach-omap2/vp44xx_data.c @@ -27,15 +27,18 @@ #include "vp.h" +static const struct omap_vp_ops omap4_vp_ops = { + .check_txdone = omap4_prm_vp_check_txdone, + .clear_txdone = omap4_prm_vp_clear_txdone, +}; + /* * VP data common to 44xx chips * XXX This stuff presumably belongs in the vp44xx.c or vp.c file. */ -static const struct omap_vp_common_data omap4_vp_common = { - .vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT, +static const struct omap_vp_common omap4_vp_common = { + .vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK, .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK, - .vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT, - .vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT, .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK, .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK, .vpconfig_initvdd = OMAP4430_INITVDD_MASK, @@ -48,53 +51,39 @@ static const struct omap_vp_common_data omap4_vp_common = { .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT, .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT, .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT, + .vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK, + .ops = &omap4_vp_ops, }; -static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = { - .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET, - .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK, -}; - -struct omap_vp_instance_data omap4_vp_mpu_data = { - .vp_common = &omap4_vp_common, +struct omap_vp_instance omap4_vp_mpu = { + .id = OMAP4_VP_VDD_MPU_ID, + .common = &omap4_vp_common, .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET, .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET, .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET, .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET, .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET, .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET, - .prm_irqst_data = &omap4_vp_mpu_prm_irqst_data, }; -static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = { - .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, - .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK, -}; - -struct omap_vp_instance_data omap4_vp_iva_data = { - .vp_common = &omap4_vp_common, +struct omap_vp_instance omap4_vp_iva = { + .id = OMAP4_VP_VDD_IVA_ID, + .common = &omap4_vp_common, .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET, .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET, .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET, .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET, .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET, .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET, - .prm_irqst_data = &omap4_vp_iva_prm_irqst_data, -}; - -static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = { - .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, - .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK, }; -struct omap_vp_instance_data omap4_vp_core_data = { - .vp_common = &omap4_vp_common, +struct omap_vp_instance omap4_vp_core = { + .id = OMAP4_VP_VDD_CORE_ID, + .common = &omap4_vp_common, .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET, .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET, .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET, .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET, .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET, .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET, - .prm_irqst_data = &omap4_vp_core_prm_irqst_data, }; - diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 7fe7406..094279a 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/delay.h> +#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/apm-emulation.h> diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 0d468e9..8169535 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -10,7 +10,6 @@ obj-n := obj- := obj-$(CONFIG_CPU_S3C2410) += s3c2410.o -obj-$(CONFIG_CPU_S3C2410) += irq.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c index 22046e2..153af8b 100644 --- a/arch/arm/mach-s5pv210/cpufreq.c +++ b/arch/arm/mach-s5pv210/cpufreq.c @@ -101,12 +101,14 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) unsigned long tmp, tmp1; void __iomem *reg = NULL; - if (ch == DMC0) + if (ch == DMC0) { reg = (S5P_VA_DMC0 + 0x30); - else if (ch == DMC1) + } else if (ch == DMC1) { reg = (S5P_VA_DMC1 + 0x30); - else + } else { printk(KERN_ERR "Cannot find DMC port\n"); + return; + } /* Find current DRAM frequency */ tmp = s5pv210_dram_conf[ch].freq; diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index c95258c..1e2aba2 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -382,10 +382,8 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) } static struct sh_mobile_sdhi_info sh_sdhi1_platdata = { - .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, - .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, - .tmio_caps = MMC_CAP_NONREMOVABLE, + .tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ, .tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .set_pwr = ag5evm_sdhi1_set_pwr, }; diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 776f205..7e1d375 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -126,7 +126,7 @@ * ------+--------------------+--------------------+------- * IRQ0 | ICR1A.IRQ0SA=0010 | SDHI2 card detect | Low * IRQ6 | ICR1A.IRQ6SA=0011 | Ether(LAN9220) | High - * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Tuch Panel | Low + * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Touch Panel | Low * IRQ8 | ICR2A.IRQ8SA=0010 | MMC/SD card detect | Low * IRQ9 | ICR2A.IRQ9SA=0010 | KEY(TCA6408) | Low * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345) | High @@ -165,10 +165,10 @@ * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. * But don't select both drivers in same time. * These uses same IRQ number for request_irq(), and aren't supporting - * IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE. + * IRQF_SHARED / IORESOURCE_IRQ_SHAREABLE. * * Actually these are old/new version of USB driver. - * This mean its register will be broken if it supports SHARD IRQ, + * This mean its register will be broken if it supports shared IRQ, */ /* @@ -562,7 +562,121 @@ out: clk_put(hdmi_ick); } -/* USB1 (Host) */ +/* USBHS0 is connected to CN22 which takes a USB Mini-B plug + * + * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug, + * but on this particular board IRQ7 is already used by + * the touch screen. This leaves us with software polling. + */ +#define USBHS0_POLL_INTERVAL (HZ * 5) + +struct usbhs_private { + unsigned int usbphyaddr; + unsigned int usbcrcaddr; + struct renesas_usbhs_platform_info info; + struct delayed_work work; + struct platform_device *pdev; +}; + +#define usbhs_get_priv(pdev) \ + container_of(renesas_usbhs_get_info(pdev), \ + struct usbhs_private, info) + +#define usbhs_is_connected(priv) \ + (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) + +static int usbhs_get_vbus(struct platform_device *pdev) +{ + return usbhs_is_connected(usbhs_get_priv(pdev)); +} + +static void usbhs_phy_reset(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* init phy */ + __raw_writew(0x8a0a, priv->usbcrcaddr); +} + +static int usbhs0_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +static void usbhs0_work_function(struct work_struct *work) +{ + struct usbhs_private *priv = container_of(work, struct usbhs_private, + work.work); + + renesas_usbhs_call_notify_hotplug(priv->pdev); + schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); +} + +static int usbhs0_hardware_init(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + priv->pdev = pdev; + INIT_DELAYED_WORK(&priv->work, usbhs0_work_function); + schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); + return 0; +} + +static void usbhs0_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + cancel_delayed_work_sync(&priv->work); +} + +static struct usbhs_private usbhs0_private = { + .usbcrcaddr = 0xe605810c, /* USBCR2 */ + .info = { + .platform_callback = { + .hardware_init = usbhs0_hardware_init, + .hardware_exit = usbhs0_hardware_exit, + .phy_reset = usbhs_phy_reset, + .get_id = usbhs0_get_id, + .get_vbus = usbhs_get_vbus, + }, + .driver_param = { + .buswait_bwait = 4, + }, + }, +}; + +static struct resource usbhs0_resources[] = { + [0] = { + .name = "USBHS0", + .start = 0xe6890000, + .end = 0xe68900e6 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x1ca0) /* USB0_USB0I0 */, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs0_device = { + .name = "renesas_usbhs", + .id = 0, + .dev = { + .platform_data = &usbhs0_private.info, + }, + .num_resources = ARRAY_SIZE(usbhs0_resources), + .resource = usbhs0_resources, +}; + +/* USBHS1 is connected to CN31 which takes a USB Mini-AB plug + * + * Use J30 to select between Host and Function. This setting + * can however not be detected by software. Hotplug of USBHS1 + * is provided via IRQ8. + */ +#define IRQ8 evt2irq(0x0300) + +/* USBHS1 USB Host support via r8a66597_hcd */ static void usb1_host_port_power(int port, int power) { if (!power) /* only power-on is supported for now */ @@ -579,9 +693,9 @@ static struct r8a66597_platdata usb1_host_data = { static struct resource usb1_host_resources[] = { [0] = { - .name = "USBHS", - .start = 0xE68B0000, - .end = 0xE68B00E6 - 1, + .name = "USBHS1", + .start = 0xe68b0000, + .end = 0xe68b00e6 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -602,37 +716,14 @@ static struct platform_device usb1_host_device = { .resource = usb1_host_resources, }; -/* USB1 (Function) */ +/* USBHS1 USB Function support via renesas_usbhs */ + #define USB_PHY_MODE (1 << 4) #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) #define USB_PHY_ON (1 << 1) #define USB_PHY_OFF (1 << 0) #define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) -struct usbhs_private { - unsigned int irq; - unsigned int usbphyaddr; - unsigned int usbcrcaddr; - struct renesas_usbhs_platform_info info; -}; - -#define usbhs_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), \ - struct usbhs_private, info) - -#define usbhs_is_connected(priv) \ - (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) - -static int usbhs1_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static int usbhs1_get_vbus(struct platform_device *pdev) -{ - return usbhs_is_connected(usbhs_get_priv(pdev)); -} - static irqreturn_t usbhs1_interrupt(int irq, void *data) { struct platform_device *pdev = data; @@ -654,12 +745,10 @@ static int usbhs1_hardware_init(struct platform_device *pdev) struct usbhs_private *priv = usbhs_get_priv(pdev); int ret; - irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH); - /* clear interrupt status */ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); - ret = request_irq(priv->irq, usbhs1_interrupt, 0, + ret = request_irq(IRQ8, usbhs1_interrupt, IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), pdev); if (ret) { dev_err(&pdev->dev, "request_irq err\n"); @@ -679,15 +768,12 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) /* clear interrupt status */ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); - free_irq(priv->irq, pdev); + free_irq(IRQ8, pdev); } -static void usbhs1_phy_reset(struct platform_device *pdev) +static int usbhs1_get_id(struct platform_device *pdev) { - struct usbhs_private *priv = usbhs_get_priv(pdev); - - /* init phy */ - __raw_writew(0x8a0a, priv->usbcrcaddr); + return USBHS_GADGET; } static u32 usbhs1_pipe_cfg[] = { @@ -710,16 +796,15 @@ static u32 usbhs1_pipe_cfg[] = { }; static struct usbhs_private usbhs1_private = { - .irq = evt2irq(0x0300), /* IRQ8 */ - .usbphyaddr = 0xE60581E2, /* USBPHY1INTAP */ - .usbcrcaddr = 0xE6058130, /* USBCR4 */ + .usbphyaddr = 0xe60581e2, /* USBPHY1INTAP */ + .usbcrcaddr = 0xe6058130, /* USBCR4 */ .info = { .platform_callback = { .hardware_init = usbhs1_hardware_init, .hardware_exit = usbhs1_hardware_exit, - .phy_reset = usbhs1_phy_reset, .get_id = usbhs1_get_id, - .get_vbus = usbhs1_get_vbus, + .phy_reset = usbhs_phy_reset, + .get_vbus = usbhs_get_vbus, }, .driver_param = { .buswait_bwait = 4, @@ -731,9 +816,9 @@ static struct usbhs_private usbhs1_private = { static struct resource usbhs1_resources[] = { [0] = { - .name = "USBHS", - .start = 0xE68B0000, - .end = 0xE68B00E6 - 1, + .name = "USBHS1", + .start = 0xe68b0000, + .end = 0xe68b00e6 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -752,7 +837,6 @@ static struct platform_device usbhs1_device = { .resource = usbhs1_resources, }; - /* LED */ static struct gpio_led mackerel_leds[] = { { @@ -1203,6 +1287,7 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, + &usbhs0_device, &usb1_host_device, &usbhs1_device, &leds_device, @@ -1301,6 +1386,7 @@ static void __init mackerel_map_io(void) #define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT10CR 0xE605100A +#define GPIO_PORT167CR 0xE60520A7 #define GPIO_PORT168CR 0xE60520A8 #define SRCR4 0xe61580bc #define USCCR1 0xE6058144 @@ -1354,17 +1440,17 @@ static void __init mackerel_init(void) gpio_request(GPIO_PORT151, NULL); /* LCDDON */ gpio_direction_output(GPIO_PORT151, 1); - /* USB enable */ - gpio_request(GPIO_FN_VBUS0_1, NULL); - gpio_request(GPIO_FN_IDIN_1_18, NULL); - gpio_request(GPIO_FN_PWEN_1_115, NULL); - gpio_request(GPIO_FN_OVCN_1_114, NULL); - gpio_request(GPIO_FN_EXTLP_1, NULL); - gpio_request(GPIO_FN_OVCN2_1, NULL); - gpio_pull_down(GPIO_PORT168CR); - - /* setup USB phy */ - __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ + /* USBHS0 */ + gpio_request(GPIO_FN_VBUS0_0, NULL); + gpio_pull_down(GPIO_PORT168CR); /* VBUS0_0 pull down */ + + /* USBHS1 */ + gpio_request(GPIO_FN_VBUS0_1, NULL); + gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */ + gpio_request(GPIO_FN_IDIN_1_113, NULL); + + /* USB phy tweak to make the r8a66597_hcd host driver work */ + __raw_writew(0x8a0a, 0xe6058130); /* USBCR4 */ /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 5d0e150..a911a60 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -250,6 +250,11 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) return IRQ_HANDLED; } +static int sh73a0_set_wake(struct irq_data *data, unsigned int on) +{ + return 0; /* always allow wakeup */ +} + void __init sh73a0_init_irq(void) { void __iomem *gic_dist_base = __io(0xf0001000); @@ -257,6 +262,7 @@ void __init sh73a0_init_irq(void) void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); gic_init(0, 29, gic_dist_base, gic_cpu_base); + gic_arch_extn.irq_set_wake = sh73a0_set_wake; register_intc_controller(&intcs_desc); diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c index 2c10190..e546017 100644 --- a/arch/arm/mach-shmobile/setup-sh7367.c +++ b/arch/arm/mach-shmobile/setup-sh7367.c @@ -38,7 +38,7 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00) }, }; @@ -57,7 +57,7 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20) }, }; @@ -76,7 +76,7 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40) }, }; @@ -95,7 +95,7 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60) }, }; @@ -114,7 +114,7 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20) }, }; @@ -133,7 +133,7 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40) }, }; @@ -152,7 +152,7 @@ static struct plat_sci_port scif6_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFB, .irqs = { evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60) }, }; diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h index c34f3ea..4f50ca8 100644 --- a/arch/arm/mach-u300/clock.h +++ b/arch/arm/mach-u300/clock.h @@ -31,7 +31,7 @@ struct clk { bool reset; __u16 clk_val; __s8 usecount; - __u32 res_reg; + void __iomem * res_reg; __u16 res_mask; bool hw_ctrld; diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h index 8b85df4..035fdc9 100644 --- a/arch/arm/mach-u300/include/mach/u300-regs.h +++ b/arch/arm/mach-u300/include/mach/u300-regs.h @@ -18,6 +18,12 @@ * the defines are used for setting up the I/O memory mapping. */ +#ifdef __ASSEMBLER__ +#define IOMEM(a) (a) +#else +#define IOMEM(a) (void __iomem *) a +#endif + /* NAND Flash CS0 */ #define U300_NAND_CS0_PHYS_BASE 0x80000000 @@ -48,13 +54,6 @@ #endif /* - * All the following peripherals are specified at their PHYSICAL address, - * so if you need to access them (in the kernel), you MUST use the macros - * defined in <asm/io.h> to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST() - * etc. - */ - -/* * AHB peripherals */ @@ -63,11 +62,11 @@ /* Vectored Interrupt Controller 0, servicing 32 interrupts */ #define U300_INTCON0_BASE (U300_AHB_PER_PHYS_BASE+0x1000) -#define U300_INTCON0_VBASE (U300_AHB_PER_VIRT_BASE+0x1000) +#define U300_INTCON0_VBASE IOMEM(U300_AHB_PER_VIRT_BASE+0x1000) /* Vectored Interrupt Controller 1, servicing 32 interrupts */ #define U300_INTCON1_BASE (U300_AHB_PER_PHYS_BASE+0x2000) -#define U300_INTCON1_VBASE (U300_AHB_PER_VIRT_BASE+0x2000) +#define U300_INTCON1_VBASE IOMEM(U300_AHB_PER_VIRT_BASE+0x2000) /* Memory Stick Pro (MSPRO) controller */ #define U300_MSPRO_BASE (U300_AHB_PER_PHYS_BASE+0x3000) @@ -115,7 +114,7 @@ /* SYSCON */ #define U300_SYSCON_BASE (U300_SLOW_PER_PHYS_BASE+0x1000) -#define U300_SYSCON_VBASE (U300_SLOW_PER_VIRT_BASE+0x1000) +#define U300_SYSCON_VBASE IOMEM(U300_SLOW_PER_VIRT_BASE+0x1000) /* Watchdog */ #define U300_WDOG_BASE (U300_SLOW_PER_PHYS_BASE+0x2000) @@ -125,7 +124,7 @@ /* APP side special timer */ #define U300_TIMER_APP_BASE (U300_SLOW_PER_PHYS_BASE+0x4000) -#define U300_TIMER_APP_VBASE (U300_SLOW_PER_VIRT_BASE+0x4000) +#define U300_TIMER_APP_VBASE IOMEM(U300_SLOW_PER_VIRT_BASE+0x4000) /* Keypad */ #define U300_KEYPAD_BASE (U300_SLOW_PER_PHYS_BASE+0x5000) @@ -181,5 +180,4 @@ * Virtual accessor macros for static devices */ - #endif diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 891cf44..18d7fa0 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -411,8 +411,7 @@ static void __init u300_timer_init(void) /* Use general purpose timer 2 as clock source */ if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC, "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) - printk(KERN_ERR "timer: failed to initialize clock " - "source %s\n", clocksource_u300_1mhz.name); + pr_err("timer: failed to initialize U300 clock source\n"); clockevents_calc_mult_shift(&clockevent_u300_1mhz, rate, APPTIMER_MIN_RANGE); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index c3c4176..4598b06 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -159,6 +159,9 @@ static void __init db8500_add_gpios(void) /* No custom data yet */ }; + if (cpu_is_u8500v2()) + pdata.supports_sleepmode = true; + dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), IRQ_DB8500_GPIO0, &pdata); } diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 285edcd..9e6b93b 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -46,12 +46,6 @@ static struct map_desc v2m_io_desc[] __initdata = { }, }; -static void __init v2m_init_early(void) -{ - ct_desc->init_early(); - versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); -} - static void __init v2m_timer_init(void) { u32 scctrl; @@ -365,6 +359,13 @@ static struct clk_lookup v2m_lookups[] = { }, }; +static void __init v2m_init_early(void) +{ + ct_desc->init_early(); + clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); + versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); +} + static void v2m_power_off(void) { if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) @@ -418,8 +419,6 @@ static void __init v2m_init(void) { int i; - clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); - platform_device_register(&v2m_pcie_i2c_device); platform_device_register(&v2m_ddc_i2c_device); platform_device_register(&v2m_flash_device); diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 8bfae96..131f381 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -24,7 +24,9 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm); /* * We fork()ed a process, and we need a new context for the child - * to run in. + * to run in. We reserve version 0 for initial tasks so we will + * always allocate an ASID. The ASID 0 is reserved for the TTBR + * register changing sequence. */ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) { @@ -34,11 +36,8 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) static void flush_context(void) { - u32 ttb; - /* Copy TTBR1 into TTBR0 */ - asm volatile("mrc p15, 0, %0, c2, c0, 1\n" - "mcr p15, 0, %0, c2, c0, 0" - : "=r" (ttb)); + /* set the reserved ASID before flushing the TLB */ + asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0)); isb(); local_flush_tlb_all(); if (icache_is_vivt_asid_tagged()) { @@ -94,14 +93,13 @@ static void reset_context(void *info) return; smp_rmb(); - asid = cpu_last_asid + cpu; + asid = cpu_last_asid + cpu + 1; flush_context(); set_mm_context(mm, asid); /* set the new ASID */ - asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (mm->context.id)); - isb(); + cpu_switch_mm(mm->pgd, mm); } #else @@ -144,13 +142,13 @@ void __new_context(struct mm_struct *mm) * to start a new version and flush the TLB. */ if (unlikely((asid & ~ASID_MASK) == 0)) { - asid = cpu_last_asid + smp_processor_id(); + asid = cpu_last_asid + smp_processor_id() + 1; flush_context(); #ifdef CONFIG_SMP smp_wmb(); smp_call_function(reset_context, NULL, 1); #endif - cpu_last_asid += NR_CPUS - 1; + cpu_last_asid += NR_CPUS; } set_mm_context(mm, asid); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 2c2cce9..c19571c 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -331,6 +331,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) #endif #ifdef CONFIG_BLK_DEV_INITRD if (phys_initrd_size && + !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { + pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n", + phys_initrd_start, phys_initrd_size); + phys_initrd_start = phys_initrd_size = 0; + } + if (phys_initrd_size && memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n", phys_initrd_start, phys_initrd_size); @@ -635,7 +641,8 @@ void __init mem_init(void) " modules : 0x%08lx - 0x%08lx (%4ld MB)\n" " .init : 0x%p" " - 0x%p" " (%4d kB)\n" " .text : 0x%p" " - 0x%p" " (%4d kB)\n" - " .data : 0x%p" " - 0x%p" " (%4d kB)\n", + " .data : 0x%p" " - 0x%p" " (%4d kB)\n" + " .bss : 0x%p" " - 0x%p" " (%4d kB)\n", MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) + (PAGE_SIZE)), @@ -657,7 +664,8 @@ void __init mem_init(void) MLK_ROUNDUP(__init_begin, __init_end), MLK_ROUNDUP(_text, _etext), - MLK_ROUNDUP(_sdata, _edata)); + MLK_ROUNDUP(_sdata, _edata), + MLK_ROUNDUP(__bss_start, __bss_stop)); #undef MLK #undef MLM diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S index e4c165c..537ffcb 100644 --- a/arch/arm/mm/proc-arm7tdmi.S +++ b/arch/arm/mm/proc-arm7tdmi.S @@ -146,7 +146,7 @@ __arm7tdmi_proc_info: .long 0 .long 0 .long v4_cache_fns - .size __arm7tdmi_proc_info, . - __arm7dmi_proc_info + .size __arm7tdmi_proc_info, . - __arm7tdmi_proc_info .type __triscenda7_proc_info, #object __triscenda7_proc_info: diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S index 7b7ebd4..546b54d 100644 --- a/arch/arm/mm/proc-arm9tdmi.S +++ b/arch/arm/mm/proc-arm9tdmi.S @@ -116,7 +116,7 @@ __arm9tdmi_proc_info: .long 0 .long 0 .long v4_cache_fns - .size __arm9tdmi_proc_info, . - __arm9dmi_proc_info + .size __arm9tdmi_proc_info, . - __arm9tdmi_proc_info .type __p2001_proc_info, #object __p2001_proc_info: diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index b3b566e..3c38678 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -108,16 +108,18 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif - mrc p15, 0, r2, c2, c0, 1 @ load TTB 1 - mcr p15, 0, r2, c2, c0, 0 @ into TTB 0 +#ifdef CONFIG_ARM_ERRATA_754322 + dsb +#endif + mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID + isb +1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 isb #ifdef CONFIG_ARM_ERRATA_754322 dsb #endif mcr p15, 0, r1, c13, c0, 1 @ set context ID isb - mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 - isb #endif mov pc, lr ENDPROC(cpu_v7_switch_mm) diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c index 3538b85..b130f60 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-dma.c +++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c @@ -139,7 +139,7 @@ static struct sdma_script_start_addrs addr_imx35_to2 = { #endif #ifdef CONFIG_SOC_IMX51 -static struct sdma_script_start_addrs addr_imx51_to1 = { +static struct sdma_script_start_addrs addr_imx51 = { .ap_2_ap_addr = 642, .uart_2_mcu_addr = 817, .mcu_2_app_addr = 747, @@ -196,7 +196,9 @@ static int __init imxXX_add_imx_dma(void) #if defined(CONFIG_SOC_IMX51) if (cpu_is_mx51()) { - imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1; + int to_version = mx51_revision() >> 4; + imx51_imx_sdma_data.pdata.to_version = to_version; + imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51; ret = imx_add_imx_sdma(&imx51_imx_sdma_data); } else #endif diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index ea19a5b..d5d7e65 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -90,6 +90,7 @@ struct nmk_gpio_platform_data { int num_gpio; u32 (*get_secondary_status)(unsigned int bank); void (*set_ioforce)(bool enable); + bool supports_sleepmode; }; #endif /* __ASM_PLAT_GPIO_H */ diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 49a4c75..9e2cd5a 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -38,6 +38,20 @@ config OMAP_DEBUG_LEDS depends on OMAP_DEBUG_DEVICES default y if LEDS_CLASS +config OMAP_RPMSG + tristate "OMAP Virtio-based remote processor messaging support" + depends on ARCH_OMAP4 + default y + select VIRTIO + select VIRTIO_RING + select OMAP_MBOX_FWK + help + Say Y if you want to enable OMAP virtio-based remote-processor + communication, currently only available with OMAP4. This is required + for offloading tasks to the remote on-chip M3s or C64x+ dsp, + usually used by multimedia frameworks to offload cpu-intensive and/or + latency-sensitive tasks. + config OMAP_SMARTREFLEX bool "SmartReflex support" depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM @@ -116,7 +130,7 @@ config OMAP_MCBSP Buffered Serial Port. config OMAP_MBOX_FWK - tristate "Mailbox framework support" + bool "Mailbox framework support" depends on ARCH_OMAP help Say Y here if you want to use OMAP Mailbox framework support for @@ -132,10 +146,10 @@ config OMAP_MBOX_KFIFO_SIZE module parameter). config OMAP_IOMMU - tristate + bool "IOMMU support for OMAP devices" config OMAP_IOMMU_DEBUG - tristate "Export OMAP IOMMU internals in DebugFS" + bool "Export OMAP IOMMU internals in DebugFS" depends on OMAP_IOMMU && DEBUG_FS help Select this to see extensive information about @@ -206,10 +220,19 @@ config OMAP_SERIAL_WAKE to data on the serial RX line. This allows you to wake the system from serial console. +# this carveout should probably become generic and not omap specific +config OMAP_CARVEOUT_MEMPOOL_SIZE + hex "Physical carveout memory pool size (Byte)" + depends on OMAP_REMOTE_PROC + default 0x700000 + help + Allocate specified size of memory at boot time so we can ioremap + it safely. + choice prompt "OMAP PM layer selection" depends on ARCH_OMAP - default OMAP_PM_NOOP + default OMAP_PM config OMAP_PM_NONE bool "No PM layer" @@ -217,6 +240,9 @@ config OMAP_PM_NONE config OMAP_PM_NOOP bool "No-op/debug PM layer" +config OMAP_PM + depends on PM + bool "OMAP PM layer implementation" endchoice endmenu diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index f0233e6..f3ab483 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -18,10 +18,10 @@ obj-$(CONFIG_ARCH_OMAP3) += omap_device.o obj-$(CONFIG_ARCH_OMAP4) += omap_device.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o +obj-$(CONFIG_OMAP_RPMSG) += omap_rpmsg.o obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o @@ -31,4 +31,5 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y) # OMAP mailbox framework obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o -obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o +obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-interface.o +obj-$(CONFIG_OMAP_PM) += omap-pm-interface.o omap-pm-helper.o diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index ea28f98..e81f9a7 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -16,19 +16,25 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/memblock.h> +#include <linux/err.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/map.h> +#include <plat/omap_hwmod.h> +#include <plat/omap_device.h> #include <plat/tc.h> #include <plat/board.h> #include <plat/mmc.h> #include <mach/gpio.h> #include <plat/menelaus.h> #include <plat/mcbsp.h> +#include <plat/mcpdm.h> #include <plat/omap44xx.h> +#include <sound/omap-abe-dsp.h> + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE) @@ -77,31 +83,38 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, #if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \ defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE) -static struct resource mcpdm_resources[] = { - { - .name = "mcpdm_mem", - .start = OMAP44XX_MCPDM_BASE, - .end = OMAP44XX_MCPDM_BASE + SZ_4K, - .flags = IORESOURCE_MEM, - }, +static struct omap_device_pm_latency omap_mcpdm_latency[] = { { - .name = "mcpdm_irq", - .start = OMAP44XX_IRQ_MCPDM, - .end = OMAP44XX_IRQ_MCPDM, - .flags = IORESOURCE_IRQ, + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, }, }; -static struct platform_device omap_mcpdm_device = { - .name = "omap-mcpdm", - .id = -1, - .num_resources = ARRAY_SIZE(mcpdm_resources), - .resource = mcpdm_resources, -}; - static void omap_init_mcpdm(void) { - (void) platform_device_register(&omap_mcpdm_device); + struct omap_hwmod *oh; + struct omap_device *od; + struct omap_mcpdm_platform_data *pdata; + + oh = omap_hwmod_lookup("mcpdm"); + if (!oh) { + printk(KERN_ERR "Could not look up mcpdm hw_mod\n"); + return; + } + + pdata = kzalloc(sizeof(struct omap_mcpdm_platform_data), GFP_KERNEL); + if (!pdata) { + printk(KERN_ERR "Could not allocate platform data\n"); + return; + } + + od = omap_device_build("omap-mcpdm", -1, oh, pdata, + sizeof(struct omap_mcpdm_platform_data), + omap_mcpdm_latency, + ARRAY_SIZE(omap_mcpdm_latency), 0); + if (IS_ERR(od)) + printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n"); } #else static inline void omap_init_mcpdm(void) {} @@ -159,6 +172,55 @@ fail: /*-------------------------------------------------------------------------*/ +#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) || \ + defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE) + +static struct omap_device_pm_latency omap_aess_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static void omap_init_aess(void) +{ + struct omap_hwmod *oh; + struct omap_device *od; + struct omap4_abe_dsp_pdata *pdata; + + oh = omap_hwmod_lookup("aess"); + if (!oh) { + printk (KERN_ERR "Could not look up aess hw_mod\n"); + return; + } + + pdata = kzalloc(sizeof(struct omap4_abe_dsp_pdata), GFP_KERNEL); + if (!pdata) { + printk(KERN_ERR "Could not allocate platform data\n"); + return; + } + + /* FIXME: Add correct context loss counter */ + //pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; + + od = omap_device_build("aess", -1, oh, pdata, + sizeof(struct omap4_abe_dsp_pdata), + omap_aess_latency, + ARRAY_SIZE(omap_aess_latency), 0); + + kfree(pdata); + + if (IS_ERR(od)) + printk(KERN_ERR "Could not build omap_device for omap-aess-audio\n"); +} +#else +static inline void omap_init_aess(void) {} +#endif + + +/*-------------------------------------------------------------------------*/ + #if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) #ifdef CONFIG_ARCH_OMAP2 @@ -190,8 +252,6 @@ static void omap_init_rng(void) static inline void omap_init_rng(void) {} #endif -/*-------------------------------------------------------------------------*/ - /* Numbering for the SPI-capable controllers when used for SPI: * spi = 1 * uwire = 2 @@ -234,13 +294,16 @@ static void omap_init_uwire(void) static inline void omap_init_uwire(void) {} #endif -#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE) +#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE) || \ + defined(CONFIG_OMAP_REMOTE_PROC) static phys_addr_t omap_dsp_phys_mempool_base; +static phys_addr_t omap_dsp_phys_mempool_size; void __init omap_dsp_reserve_sdram_memblock(void) { - phys_addr_t size = CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE; + /* ignoring TIDSPBRIDGE for a moment here... */ + phys_addr_t size = CONFIG_OMAP_CARVEOUT_MEMPOOL_SIZE; phys_addr_t paddr; if (!size) @@ -256,6 +319,7 @@ void __init omap_dsp_reserve_sdram_memblock(void) memblock_remove(paddr, size); omap_dsp_phys_mempool_base = paddr; + omap_dsp_phys_mempool_size = size; } phys_addr_t omap_dsp_get_mempool_base(void) @@ -263,6 +327,12 @@ phys_addr_t omap_dsp_get_mempool_base(void) return omap_dsp_phys_mempool_base; } EXPORT_SYMBOL(omap_dsp_get_mempool_base); + +phys_addr_t omap_dsp_get_mempool_size(void) +{ + return omap_dsp_phys_mempool_size; +} +EXPORT_SYMBOL(omap_dsp_get_mempool_size); #endif /* @@ -292,6 +362,7 @@ static int __init omap_init_devices(void) */ omap_init_rng(); omap_init_mcpdm(); + omap_init_aess(); omap_init_uwire(); return 0; } diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 3341ca4..f8dc82f 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -113,16 +113,6 @@ static inline int omap1_i2c_add_bus(int bus_id) #ifdef CONFIG_ARCH_OMAP2PLUS -/* - * XXX This function is a temporary compatibility wrapper - only - * needed until the I2C driver can be converted to call - * omap_pm_set_max_dev_wakeup_lat() and handle a return code. - */ -static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) -{ - omap_pm_set_max_mpu_wakeup_lat(dev, t); -} - static struct omap_device_pm_latency omap_i2c_latency[] = { [0] = { .deactivate_func = omap_device_idle_hwmods, @@ -158,8 +148,8 @@ static inline int omap2_i2c_add_bus(int bus_id) * completes. * Only omap3 has support for constraints */ - if (cpu_is_omap34xx()) - pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; + if (cpu_is_omap34xx() || cpu_is_omap44xx()) + pdata->needs_wakeup_latency = true; od = omap_device_build(name, bus_id, oh, pdata, sizeof(struct omap_i2c_bus_platform_data), omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0); diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h index f1899a3..324446b 100644 --- a/arch/arm/plat-omap/include/plat/clkdev_omap.h +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h @@ -39,11 +39,13 @@ struct omap_clk { #define CK_36XX (1 << 10) /* 36xx/37xx-specific clocks */ #define CK_443X (1 << 11) #define CK_TI816X (1 << 12) +#define CK_446X (1 << 13) #define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS) #define CK_AM35XX (CK_3505 | CK_3517) /* all Sitara AM35xx */ #define CK_3XXX (CK_34XX | CK_AM35XX | CK_36XX) +#define CK_44XX (CK_443X | CK_446X) #endif diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index 006e599..12a9ced 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -56,12 +56,14 @@ struct clkops { #define RATE_IN_3430ES1 (1 << 2) /* 3430ES1 rates only */ #define RATE_IN_3430ES2PLUS (1 << 3) /* 3430 ES >= 2 rates only */ #define RATE_IN_36XX (1 << 4) -#define RATE_IN_4430 (1 << 5) +#define RATE_IN_443X (1 << 5) #define RATE_IN_TI816X (1 << 6) +#define RATE_IN_446X (1 << 7) #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) #define RATE_IN_34XX (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS) #define RATE_IN_3XXX (RATE_IN_34XX | RATE_IN_36XX) +#define RATE_IN_44XX (RATE_IN_443X | RATE_IN_446X) /* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */ #define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX) diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 5288130..b2c2247 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -53,6 +53,7 @@ struct omap_globals { unsigned long sms; /* SDRAM Memory Scheduler */ unsigned long ctrl; /* System Control Module */ unsigned long ctrl_pad; /* PAD Control Module */ + unsigned long ctrl_wk_pad; /* PAD Control WakeUp Module */ unsigned long prm; /* Power and Reset Management */ unsigned long cm; /* Clock Management */ unsigned long cm2; diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index 8198bb6..3faa251 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -88,6 +88,7 @@ unsigned int omap_rev(void); * cpu_is_omap243x(): True for OMAP2430 * cpu_is_omap343x(): True for OMAP3430 * cpu_is_omap443x(): True for OMAP4430 + * cpu_is_omap446x(): True for OMAP4460 */ #define GET_OMAP_CLASS (omap_rev() & 0xff) @@ -123,6 +124,7 @@ IS_OMAP_SUBCLASS(243x, 0x243) IS_OMAP_SUBCLASS(343x, 0x343) IS_OMAP_SUBCLASS(363x, 0x363) IS_OMAP_SUBCLASS(443x, 0x443) +IS_OMAP_SUBCLASS(446x, 0x446) IS_TI_SUBCLASS(816x, 0x816) @@ -137,6 +139,7 @@ IS_TI_SUBCLASS(816x, 0x816) #define cpu_is_ti816x() 0 #define cpu_is_omap44xx() 0 #define cpu_is_omap443x() 0 +#define cpu_is_omap446x() 0 #if defined(MULTI_OMAP1) # if defined(CONFIG_ARCH_OMAP730) @@ -361,8 +364,10 @@ IS_OMAP_TYPE(3517, 0x3517) # if defined(CONFIG_ARCH_OMAP4) # undef cpu_is_omap44xx # undef cpu_is_omap443x +# undef cpu_is_omap446x # define cpu_is_omap44xx() is_omap44xx() # define cpu_is_omap443x() is_omap443x() +# define cpu_is_omap446x() is_omap446x() # endif /* Macros to detect if we have OMAP1 or OMAP2 */ @@ -410,6 +415,9 @@ IS_OMAP_TYPE(3517, 0x3517) #define OMAP4430_REV_ES2_1 (OMAP443X_CLASS | (0x21 << 8)) #define OMAP4430_REV_ES2_2 (OMAP443X_CLASS | (0x22 << 8)) +#define OMAP446X_CLASS 0x44600044 +#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8)) + /* * omap_chip bits * @@ -439,14 +447,19 @@ IS_OMAP_TYPE(3517, 0x3517) #define CHIP_IS_OMAP4430ES2_1 (1 << 12) #define CHIP_IS_OMAP4430ES2_2 (1 << 13) #define CHIP_IS_TI816X (1 << 14) +#define CHIP_IS_OMAP4460ES1_0 (1 << 15) #define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430) -#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1 | \ +#define CHIP_IS_OMAP443X (CHIP_IS_OMAP4430ES1 | \ CHIP_IS_OMAP4430ES2 | \ CHIP_IS_OMAP4430ES2_1 | \ CHIP_IS_OMAP4430ES2_2) +#define CHIP_IS_OMAP446X CHIP_IS_OMAP4460ES1_0 + +#define CHIP_IS_OMAP44XX (CHIP_IS_OMAP443X | CHIP_IS_OMAP446X) + /* * "GE" here represents "greater than or equal to" in terms of ES * levels. So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430 diff --git a/arch/arm/plat-omap/include/plat/dsp.h b/arch/arm/plat-omap/include/plat/dsp.h index 9c604b3..31ee386 100644 --- a/arch/arm/plat-omap/include/plat/dsp.h +++ b/arch/arm/plat-omap/include/plat/dsp.h @@ -22,10 +22,14 @@ struct omap_dsp_platform_data { phys_addr_t phys_mempool_size; }; -#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE) +#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE) || \ + defined(CONFIG_OMAP_REMOTE_PROC) extern void omap_dsp_reserve_sdram_memblock(void); #else static inline void omap_dsp_reserve_sdram_memblock(void) { } #endif +phys_addr_t omap_dsp_get_mempool_size(void); +phys_addr_t omap_dsp_get_mempool_base(void); + #endif diff --git a/arch/arm/plat-omap/include/plat/dsscomp.h b/arch/arm/plat-omap/include/plat/dsscomp.h new file mode 100644 index 0000000..acafe0f --- /dev/null +++ b/arch/arm/plat-omap/include/plat/dsscomp.h @@ -0,0 +1,23 @@ +#ifndef _ARCH_ARM_PLAT_OMAP_DSSCOMP_H +#define _ARCH_ARM_PLAT_OMAP_DSSCOMP_H + +#include <video/omapdss.h> + +/* queuing operations */ +typedef struct dsscomp_data *dsscomp_t; /* handle */ + +dsscomp_t dsscomp_new_sync_id(struct omap_overlay_manager *mgr, u32 sync_id); +u32 dsscomp_first_sync_id(struct omap_overlay_manager *mgr); +dsscomp_t dsscomp_find(struct omap_overlay_manager *mgr, u32 sync_id); +u32 dsscomp_get_ovls(dsscomp_t comp); +int dsscomp_set_ovl(dsscomp_t comp, struct dss2_ovl_info *ovl); +int dsscomp_get_ovl(dsscomp_t comp, u32 ix, struct dss2_ovl_info *ovl); +int dsscomp_set_mgr(dsscomp_t comp, struct dss2_mgr_info *mgr); +int dsscomp_get_mgr(dsscomp_t comp, struct dss2_mgr_info *mgr); +int dsscomp_setup(dsscomp_t comp, enum dsscomp_setup_mode mode, + struct dss2_rect_t win); +int dsscomp_apply(dsscomp_t comp); +int dsscomp_wait(dsscomp_t comp, enum dsscomp_wait_phase phase, int timeout); +void dsscomp_drop(dsscomp_t c); + +#endif diff --git a/arch/arm/plat-omap/include/plat/flash.h b/arch/arm/plat-omap/include/plat/flash.h index 3083195..0d88499 100644 --- a/arch/arm/plat-omap/include/plat/flash.h +++ b/arch/arm/plat-omap/include/plat/flash.h @@ -11,6 +11,7 @@ #include <linux/mtd/map.h> +struct platform_device; extern void omap1_set_vpp(struct platform_device *pdev, int enable); #endif diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/plat-omap/include/plat/gpu.h index 2854129..70dcc92 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/plat-omap/include/plat/gpu.h @@ -1,7 +1,5 @@ -/* linux/arch/arm/mach-s3c2410/irq.c - * - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> +/* + * arch/arm/plat-omap/include/plat/gpu.h * * 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 @@ -10,25 +8,26 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/syscore_ops.h> +#ifndef OMAP_GPU_H +#define OMAP_GPU_H -#include <plat/cpu.h> -#include <plat/pm.h> +#include <plat/omap-pm.h> +#include <linux/platform_device.h> -struct syscore_ops s3c24xx_irq_syscore_ops = { - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, +struct gpu_platform_data { + void (*set_min_bus_tput)(struct device *dev, u8 agent_id, + unsigned long r); + int (*device_enable) (struct platform_device *pdev); + int (*device_shutdown) (struct platform_device *pdev); + int (*device_idle) (struct platform_device *pdev); }; + +#endif diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h index 174f1b9..e043a53 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -28,7 +28,6 @@ struct iotlb_entry { struct iommu { const char *name; struct module *owner; - struct clk *clk; void __iomem *regbase; struct device *dev; void *isr_priv; @@ -53,6 +52,7 @@ struct iommu { void *ctx; /* iommu context: registres saved area */ u32 da_start; u32 da_end; + struct platform_device *pdev; }; struct cr_regs { @@ -104,10 +104,12 @@ struct iommu_functions { struct iommu_platform_data { const char *name; - const char *clk_name; + const char *oh_name; const int nr_tlb_entries; u32 da_start; u32 da_end; + int irq; + void __iomem *io_base; }; /* IOMMU errors */ diff --git a/arch/arm/plat-omap/include/plat/iovmm.h b/arch/arm/plat-omap/include/plat/iovmm.h index 32a2f6c..e992b96 100644 --- a/arch/arm/plat-omap/include/plat/iovmm.h +++ b/arch/arm/plat-omap/include/plat/iovmm.h @@ -29,9 +29,6 @@ struct iovm_struct { * lower 16 bit is used for h/w and upper 16 bit is for s/w. */ #define IOVMF_SW_SHIFT 16 -#define IOVMF_HW_SIZE (1 << IOVMF_SW_SHIFT) -#define IOVMF_HW_MASK (IOVMF_HW_SIZE - 1) -#define IOVMF_SW_MASK (~IOVMF_HW_MASK)UL /* * iovma: h/w flags derived from cam and ram attribute diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 5a25098..2cfba51 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -407,11 +407,19 @@ #endif #define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) +#define TWL6040_CODEC_IRQ_BASE TWL6030_IRQ_END +#ifdef CONFIG_TWL6040_CODEC +#define TWL6040_CODEC_NR_IRQS 6 +#else +#define TWL6040_CODEC_NR_IRQS 0 +#endif +#define TWL6040_CODEC_IRQ_END (TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS) + /* Total number of interrupts depends on the enabled blocks above */ -#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END) +#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END) #define TWL_IRQ_END TWL4030_GPIO_IRQ_END #else -#define TWL_IRQ_END TWL6030_IRQ_END +#define TWL_IRQ_END TWL6040_CODEC_IRQ_END #endif /* GPMC related */ diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index f8f690a..ddada0b 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -403,6 +403,8 @@ struct omap_mcbsp_platform_data { #endif u16 buffer_size; unsigned int mcbsp_config_type; + char clks_pad_src[30]; + char clks_prcm_src[30]; }; struct omap_mcbsp_st_data { @@ -448,6 +450,8 @@ struct omap_mcbsp { struct clk *fclk; #ifdef CONFIG_ARCH_OMAP3 struct omap_mcbsp_st_data *st_data; +#endif +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) int dma_op_mode; u16 max_tx_thres; u16 max_rx_thres; @@ -474,7 +478,7 @@ int omap_mcbsp_init(void); void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, struct omap_mcbsp_platform_data *config, int size); void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); -#ifdef CONFIG_ARCH_OMAP3 +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); diff --git a/arch/arm/plat-omap/include/plat/mcpdm.h b/arch/arm/plat-omap/include/plat/mcpdm.h new file mode 100644 index 0000000..1ed2b8f --- /dev/null +++ b/arch/arm/plat-omap/include/plat/mcpdm.h @@ -0,0 +1,30 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __OMAP_PLAT_MCPDM_H__ +#define __OMAP_PLAT_MCPDM_H__ + +#include <linux/platform_device.h> + +struct omap_mcpdm_platform_data { + int (*device_enable) (struct platform_device *pdev); + int (*device_shutdown) (struct platform_device *pdev); + int (*device_idle) (struct platform_device *pdev); +}; + +#endif diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index f38fef9..f24ed41 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -101,12 +101,16 @@ struct omap_mmc_platform_data { /* If using power_saving and the MMC power is not to go off */ unsigned no_off:1; + /* eMMC does not handle power off when not in sleep state */ + unsigned no_regulator_off_init:1; + /* Regulator off remapped to sleep */ unsigned vcc_aux_disable_is_sleep:1; /* we can put the features above into this variable */ -#define HSMMC_HAS_PBIAS (1 << 0) -#define HSMMC_HAS_UPDATED_RESET (1 << 1) +#define HSMMC_HAS_PBIAS (1 << 0) +#define HSMMC_HAS_UPDATED_RESET (1 << 1) +#define HSMMC_HAS_48MHZ_MASTER_CLK (1 << 2) unsigned features; int switch_pin; /* gpio (card detect) */ diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 68df031..1bfdf63 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -17,7 +17,9 @@ #include <linux/device.h> #include <linux/cpufreq.h> #include <linux/clk.h> +#include <linux/pm_qos_params.h> #include <linux/opp.h> +#include <linux/pm_qos_params.h> /* * agent_id values for use with omap_pm_set_min_bus_tput(): @@ -73,7 +75,8 @@ void omap_pm_if_exit(void); /** * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency - * @dev: struct device * requesting the constraint + * @qos_request: handle for the constraint. The pointer should be + * initialized to NULL * @t: maximum MPU wakeup latency in microseconds * * Request that the maximum interrupt latency for the MPU to be no @@ -105,7 +108,8 @@ void omap_pm_if_exit(void); * Returns -EINVAL for an invalid argument, -ERANGE if the constraint * is not satisfiable, or 0 upon success. */ -int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); +int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **qos_request, + long t); /** @@ -132,12 +136,12 @@ int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); * * Multiple calls to omap_pm_set_min_bus_tput() will replace the * previous rate value for this device. To remove the interconnect - * throughput restriction for this device, call with r = 0. + * throughput restriction for this device, call with r = -1. * * Returns -EINVAL for an invalid argument, -ERANGE if the constraint * is not satisfiable, or 0 upon success. */ -int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r); /** @@ -172,7 +176,8 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, /** * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency - * @dev: struct device * + * @qos_request: handle for the constraint. The pointer should be + * initialized to NULL * @t: maximum DMA transfer start latency in microseconds * * Request that the maximum system DMA transfer start latency for this @@ -197,7 +202,8 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, * Returns -EINVAL for an invalid argument, -ERANGE if the constraint * is not satisfiable, or 0 upon success. */ -int omap_pm_set_max_sdma_lat(struct device *dev, long t); +int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, + long t); /** @@ -350,10 +356,19 @@ unsigned long omap_pm_cpu_get_freq(void); * driver must restore device context. If the number of context losses * exceeds the maximum positive integer, the function will wrap to 0 and * continue counting. Returns the number of context losses for this device, - * or negative value upon error. + * or -EINVAL upon error. */ int omap_pm_get_dev_context_loss_count(struct device *dev); + +/** + * omap_pm_set_min_mpu_freq - sets the min frequency the mpu should be allowed + * to run. The function works with a granularity of 1000000. Any frequency requested, + * will set the mpu frequency to the closet higher frequency that can match the request. + * to release the constraint, the f parameter should be passed as -1. + */ +int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f); + void omap_pm_enable_off_mode(void); void omap_pm_disable_off_mode(void); diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 2682043..71e238e 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -112,5 +112,6 @@ struct uart_omap_port { char name[20]; unsigned long port_activity; }; +int omap_uart_active(int num, u32 timeout); #endif /* __OMAP_SERIAL_H__ */ diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h index ea2b8a6..c6d131d 100644 --- a/arch/arm/plat-omap/include/plat/omap44xx.h +++ b/arch/arm/plat-omap/include/plat/omap44xx.h @@ -34,6 +34,7 @@ #define OMAP44XX_GPMC_BASE 0x50000000 #define OMAP443X_SCM_BASE 0x4a002000 #define OMAP443X_CTRL_BASE 0x4a100000 +#define OMAP443X_CTRL_WK_BASE 0x4a31e000 #define OMAP44XX_IC_BASE 0x48200000 #define OMAP44XX_IVA_INTC_BASE 0x40000000 #define IRQ_SIR_IRQ 0x0040 @@ -45,6 +46,7 @@ #define OMAP44XX_WKUPGEN_BASE 0x48281000 #define OMAP44XX_MCPDM_BASE 0x40132000 #define OMAP44XX_MCPDM_L3_BASE 0x49032000 +#define OMAP44XX_SAR_RAM_BASE 0x4a326000 #define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000) #define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000) diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 8658e2d..a74663a 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -519,8 +519,6 @@ struct omap_hwmod { const char *main_clk; struct clk *_clk; struct omap_hwmod_opt_clk *opt_clks; - char *vdd_name; - struct voltagedomain *voltdm; struct omap_hwmod_ocp_if **masters; /* connect to *_IA */ struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */ void *dev_attr; diff --git a/arch/arm/plat-omap/include/plat/remoteproc.h b/arch/arm/plat-omap/include/plat/remoteproc.h new file mode 100644 index 0000000..5f7ffbb --- /dev/null +++ b/arch/arm/plat-omap/include/plat/remoteproc.h @@ -0,0 +1,42 @@ +/* + * Remote Processor - omap-specific bits + * + * Copyright (C) 2011 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _PLAT_REMOTEPROC_H +#define _PLAT_REMOTEPROC_H + +#include <linux/remoteproc.h> + +/* + * struct omap_rproc_pdata - platform data for the omap rproc implementation + * + * @name: human readable name of the rproc, cannot exceed RPROC_MAN_NAME bytes + * @iommu_name: iommu device we're behind of + * @oh_name: omap hwmod device + * @oh_name_opt: optional, secondary omap hwmod device + * @firmware: name of firmware file to be loaded + * @ops: platform-specific start/stop rproc handlers + * @memory_maps: table of da-to-pa iommu memory maps + */ +struct omap_rproc_pdata { + const char *name; + const char *iommu_name; + const char *oh_name; + const char *oh_name_opt; + const char *firmware; + const struct rproc_ops *ops; + const struct rproc_mem_entry *memory_maps; +}; + +#endif /* _PLAT_REMOTEPROC_H */ diff --git a/arch/arm/plat-omap/include/plat/rpmsg.h b/arch/arm/plat-omap/include/plat/rpmsg.h new file mode 100644 index 0000000..c78b9d2 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/rpmsg.h @@ -0,0 +1,68 @@ +/* + * Remote processor messaging + * + * Copyright(c) 2011 Texas Instruments. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PLAT_RPMSG_H +#define _PLAT_RPMSG_H + +/* + * enum - Predefined Mailbox Messages + * + * @RP_MBOX_READY: informs the M3's that we're up and running. will be + * followed by another mailbox message that carries the A9's virtual address + * of the shared buffer. This would allow the A9's drivers to send virtual + * addresses of the buffers. + * + * @RP_MBOX_PENDING_MSG: informs the receiver that there is an inbound + * message waiting in its own receive-side vring. please note that currently + * this message is optional: alternatively, one can explicitly send the index + * of the triggered virtqueue itself. the preferred approach will be decided + * as we progress and experiment with those design ideas. + * + * @RP_MBOX_CRASH: this message is sent upon a BIOS exception + * + * @RP_MBOX_ECHO_REQUEST: a mailbox-level "ping" message. + * + * @RP_MBOX_ECHO_REPLY: a mailbox-level reply to a "ping" + * + * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the + * recovery mechanism (to some extent). will trigger a @RP_MBOX_CRASH reply. + */ +enum { + RP_MBOX_READY = 0xFFFFFF00, + RP_MBOX_PENDING_MSG = 0xFFFFFF01, + RP_MBOX_CRASH = 0xFFFFFF02, + RP_MBOX_ECHO_REQUEST = 0xFFFFFF03, + RP_MBOX_ECHO_REPLY = 0xFFFFFF04, + RP_MBOX_ABORT_REQUEST = 0xFFFFFF05, +}; + +#endif /* _PLAT_RPMSG_H */ diff --git a/arch/arm/plat-omap/include/plat/rpres.h b/arch/arm/plat-omap/include/plat/rpres.h new file mode 100644 index 0000000..c80514b --- /dev/null +++ b/arch/arm/plat-omap/include/plat/rpres.h @@ -0,0 +1,49 @@ +/* + * Remote processor resources + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * + * Fernando Guzman Lugo <fernando.lugo@ti.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + */ + +#ifndef _PLAT_OMAP_RPRES_H +#define _PLAT_OMAP_RPRES_H + +enum { + RPRES_INACTIVE, + RPRES_ACTIVE, +}; + +struct rpres_ops { + int (*start)(struct platform_device *pdev); + int (*stop)(struct platform_device *pdev); + /* no PM for the momment */ + //int (*set_constraint)(struct device *dev, void *arg); + //int (*remove_constraint)(struct device *dev); +}; + +struct rpres_platform_data { + const char *name; + const char *oh_name; + struct omap_hwmod *oh; + struct rpres_ops *ops; + struct clk *opt_clk; + const char *opt_clk_name; +}; + +struct rpres { + struct list_head next; + const char *name; + struct platform_device *pdev; + int state; + struct mutex lock; +}; + +struct rpres *rpres_get(const char *); +void rpres_put(struct rpres *); +#endif /* _PLAT_OMAP_RPRES_H */ diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 34fc31e..882ba78 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -107,11 +107,8 @@ static int iommu_enable(struct iommu *obj) if (!arch_iommu) return -ENODEV; - clk_enable(obj->clk); - err = arch_iommu->enable(obj); - clk_disable(obj->clk); return err; } @@ -120,11 +117,7 @@ static void iommu_disable(struct iommu *obj) if (!obj) return; - clk_enable(obj->clk); - arch_iommu->disable(obj); - - clk_disable(obj->clk); } /* @@ -247,8 +240,6 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) if (!obj || !obj->nr_tlb_entries || !e) return -EINVAL; - clk_enable(obj->clk); - iotlb_lock_get(obj, &l); if (l.base == obj->nr_tlb_entries) { dev_warn(obj->dev, "%s: preserve entries full\n", __func__); @@ -277,7 +268,6 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) cr = iotlb_alloc_cr(obj, e); if (IS_ERR(cr)) { - clk_disable(obj->clk); return PTR_ERR(cr); } @@ -291,7 +281,6 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) l.vict = l.base; iotlb_lock_set(obj, &l); out: - clk_disable(obj->clk); return err; } EXPORT_SYMBOL_GPL(load_iotlb_entry); @@ -308,8 +297,6 @@ void flush_iotlb_page(struct iommu *obj, u32 da) int i; struct cr_regs cr; - clk_enable(obj->clk); - for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { u32 start; size_t bytes; @@ -327,7 +314,6 @@ void flush_iotlb_page(struct iommu *obj, u32 da) iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); } } - clk_disable(obj->clk); if (i == obj->nr_tlb_entries) dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); @@ -362,15 +348,11 @@ void flush_iotlb_all(struct iommu *obj) { struct iotlb_lock l; - clk_enable(obj->clk); - l.base = 0; l.vict = 0; iotlb_lock_set(obj, &l); iommu_write_reg(obj, 1, MMU_GFLUSH); - - clk_disable(obj->clk); } EXPORT_SYMBOL_GPL(flush_iotlb_all); @@ -385,9 +367,7 @@ EXPORT_SYMBOL_GPL(flush_iotlb_all); */ void iommu_set_twl(struct iommu *obj, bool on) { - clk_enable(obj->clk); arch_iommu->set_twl(obj, on); - clk_disable(obj->clk); } EXPORT_SYMBOL_GPL(iommu_set_twl); @@ -398,12 +378,8 @@ ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes) if (!obj || !buf) return -EINVAL; - clk_enable(obj->clk); - bytes = arch_iommu->dump_ctx(obj, buf, bytes); - clk_disable(obj->clk); - return bytes; } EXPORT_SYMBOL_GPL(iommu_dump_ctx); @@ -415,7 +391,6 @@ static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num) struct cr_regs tmp; struct cr_regs *p = crs; - clk_enable(obj->clk); iotlb_lock_get(obj, &saved); for_each_iotlb_cr(obj, num, i, tmp) { @@ -425,7 +400,6 @@ static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num) } iotlb_lock_set(obj, &saved); - clk_disable(obj->clk); return p - crs; } @@ -471,22 +445,15 @@ EXPORT_SYMBOL_GPL(foreach_iommu_device); */ static void flush_iopgd_range(u32 *first, u32 *last) { - /* FIXME: L2 cache should be taken care of if it exists */ - do { - asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pgd" - : : "r" (first)); - first += L1_CACHE_BYTES / sizeof(*first); - } while (first <= last); + dmac_flush_range(first, last); + outer_flush_range(virt_to_phys(first), virt_to_phys(last)); } + static void flush_iopte_range(u32 *first, u32 *last) { - /* FIXME: L2 cache should be taken care of if it exists */ - do { - asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pte" - : : "r" (first)); - first += L1_CACHE_BYTES / sizeof(*first); - } while (first <= last); + dmac_flush_range(first, last); + outer_flush_range(virt_to_phys(first), virt_to_phys(last)); } static void iopte_free(u32 *iopte) @@ -515,7 +482,7 @@ static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da) return ERR_PTR(-ENOMEM); *iopgd = virt_to_phys(iopte) | IOPGD_TABLE; - flush_iopgd_range(iopgd, iopgd); + flush_iopgd_range(iopgd, iopgd + 1); dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte); } else { @@ -544,7 +511,7 @@ static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot) } *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION; - flush_iopgd_range(iopgd, iopgd); + flush_iopgd_range(iopgd, iopgd + 1); return 0; } @@ -561,7 +528,7 @@ static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot) for (i = 0; i < 16; i++) *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER; - flush_iopgd_range(iopgd, iopgd + 15); + flush_iopgd_range(iopgd, iopgd + 16); return 0; } @@ -574,7 +541,7 @@ static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot) return PTR_ERR(iopte); *iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL; - flush_iopte_range(iopte, iopte); + flush_iopte_range(iopte, iopte + 1); dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n", __func__, da, pa, iopte, *iopte); @@ -599,7 +566,7 @@ static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot) for (i = 0; i < 16; i++) *(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE; - flush_iopte_range(iopte, iopte + 15); + flush_iopte_range(iopte, iopte + 16); return 0; } @@ -770,7 +737,7 @@ static void iopgtable_clear_entry_all(struct iommu *obj) iopte_free(iopte_offset(iopgd, 0)); *iopgd = 0; - flush_iopgd_range(iopgd, iopgd); + flush_iopgd_range(iopgd, iopgd + 1); } flush_iotlb_all(obj); @@ -790,9 +757,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) if (!obj->refcount) return IRQ_NONE; - clk_enable(obj->clk); errs = iommu_report_fault(obj, &da); - clk_disable(obj->clk); if (errs == 0) return IRQ_HANDLED; @@ -951,25 +916,17 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) { int err = -ENODEV; void *p; - int irq; struct iommu *obj; - struct resource *res; struct iommu_platform_data *pdata = pdev->dev.platform_data; - if (pdev->num_resources != 2) - return -EINVAL; - obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); if (!obj) return -ENOMEM; - obj->clk = clk_get(&pdev->dev, pdata->clk_name); - if (IS_ERR(obj->clk)) - goto err_clk; - obj->nr_tlb_entries = pdata->nr_tlb_entries; obj->name = pdata->name; obj->dev = &pdev->dev; + obj->pdev = pdev; obj->ctx = (void *)obj + sizeof(*obj); obj->da_start = pdata->da_start; obj->da_end = pdata->da_end; @@ -979,31 +936,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) spin_lock_init(&obj->page_table_lock); INIT_LIST_HEAD(&obj->mmap); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - err = -ENODEV; - goto err_mem; - } - - res = request_mem_region(res->start, resource_size(res), - dev_name(&pdev->dev)); - if (!res) { - err = -EIO; - goto err_mem; - } - - obj->regbase = ioremap(res->start, resource_size(res)); - if (!obj->regbase) { - err = -ENOMEM; - goto err_ioremap; - } + obj->regbase = pdata->io_base; - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - err = -ENODEV; - goto err_irq; - } - err = request_irq(irq, iommu_fault_handler, IRQF_SHARED, + err = request_irq(pdata->irq, iommu_fault_handler, IRQF_SHARED, dev_name(&pdev->dev), obj); if (err < 0) goto err_irq; @@ -1024,36 +959,24 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) return 0; err_pgd: - free_irq(irq, obj); + free_irq(pdata->irq, obj); err_irq: - iounmap(obj->regbase); -err_ioremap: - release_mem_region(res->start, resource_size(res)); -err_mem: - clk_put(obj->clk); -err_clk: kfree(obj); return err; } static int __devexit omap_iommu_remove(struct platform_device *pdev) { - int irq; - struct resource *res; struct iommu *obj = platform_get_drvdata(pdev); + struct iommu_platform_data *pdata = pdev->dev.platform_data; + + free_irq(pdata->irq, obj); platform_set_drvdata(pdev, NULL); iopgtable_clear_entry_all(obj); free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE)); - irq = platform_get_irq(pdev, 0); - free_irq(irq, obj); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - iounmap(obj->regbase); - - clk_put(obj->clk); dev_info(&pdev->dev, "%s removed\n", obj->name); kfree(obj); return 0; diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index 51ef43e..83a37c5 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -648,7 +648,6 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt, return PTR_ERR(va); } - flags &= IOVMF_HW_MASK; flags |= IOVMF_DISCONT; flags |= IOVMF_MMIO; @@ -706,7 +705,6 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) if (!va) return -ENOMEM; - flags &= IOVMF_HW_MASK; flags |= IOVMF_DISCONT; flags |= IOVMF_ALLOC; @@ -795,7 +793,6 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, if (!va) return -ENOMEM; - flags &= IOVMF_HW_MASK; flags |= IOVMF_LINEAR; flags |= IOVMF_MMIO; @@ -853,7 +850,6 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) return -ENOMEM; pa = virt_to_phys(va); - flags &= IOVMF_HW_MASK; flags |= IOVMF_LINEAR; flags |= IOVMF_ALLOC; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 5587acf..fb5571d 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -75,6 +75,11 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) { return __raw_readl(mcbsp->st_data->io_base_st + reg); } + +#define MCBSP_ST_READ(mcbsp, reg) \ + omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg) +#define MCBSP_ST_WRITE(mcbsp, reg, val) \ + omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) #endif #define MCBSP_READ(mcbsp, reg) \ @@ -84,11 +89,6 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) #define MCBSP_READ_CACHE(mcbsp, reg) \ omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1) -#define MCBSP_ST_READ(mcbsp, reg) \ - omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg) -#define MCBSP_ST_WRITE(mcbsp, reg, val) \ - omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) - static void omap_mcbsp_dump_reg(u8 id) { struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); @@ -292,14 +292,16 @@ int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream) } EXPORT_SYMBOL(omap_mcbsp_dma_reg_params); -#ifdef CONFIG_ARCH_OMAP3 +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) static struct omap_device *find_omap_device_by_dev(struct device *dev) { struct platform_device *pdev = container_of(dev, struct platform_device, dev); return container_of(pdev, struct omap_device, pdev); } +#endif +#ifdef CONFIG_ARCH_OMAP3 static void omap_st_on(struct omap_mcbsp *mcbsp) { unsigned int w; @@ -550,7 +552,12 @@ int omap_st_is_enabled(unsigned int id) return st_data->enabled; } EXPORT_SYMBOL(omap_st_is_enabled); +#else +static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} +static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} +#endif +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) /* * omap_mcbsp_set_rx_threshold configures the transmit threshold in words. * The threshold parameter is 1 based, and it is converted (threshold - 1) @@ -754,8 +761,6 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) #else static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} -static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} -static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} #endif /* @@ -1522,7 +1527,7 @@ void omap_mcbsp_set_spi_mode(unsigned int id, } EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); -#ifdef CONFIG_ARCH_OMAP3 +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) #define THRESHOLD_PROP_BUILDER(prop) \ @@ -1613,6 +1618,29 @@ unlock: static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); +static const struct attribute *additional_attrs[] = { + &dev_attr_max_tx_thres.attr, + &dev_attr_max_rx_thres.attr, + &dev_attr_dma_op_mode.attr, + NULL, +}; + +static const struct attribute_group additional_attr_group = { + .attrs = (struct attribute **)additional_attrs, +}; + +static inline int __devinit omap_additional_add(struct device *dev) +{ + return sysfs_create_group(&dev->kobj, &additional_attr_group); +} + +static inline void __devexit omap_additional_remove(struct device *dev) +{ + sysfs_remove_group(&dev->kobj, &additional_attr_group); +} +#endif + +#ifdef CONFIG_ARCH_OMAP3 static ssize_t st_taps_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1671,27 +1699,6 @@ out: static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store); -static const struct attribute *additional_attrs[] = { - &dev_attr_max_tx_thres.attr, - &dev_attr_max_rx_thres.attr, - &dev_attr_dma_op_mode.attr, - NULL, -}; - -static const struct attribute_group additional_attr_group = { - .attrs = (struct attribute **)additional_attrs, -}; - -static inline int __devinit omap_additional_add(struct device *dev) -{ - return sysfs_create_group(&dev->kobj, &additional_attr_group); -} - -static inline void __devexit omap_additional_remove(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &additional_attr_group); -} - static const struct attribute *sidetone_attrs[] = { &dev_attr_st_taps.attr, NULL, @@ -1749,11 +1756,16 @@ static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp) kfree(st_data); } } +#else +static inline int __devinit omap_st_add(struct omap_mcbsp *mcbsp) { return 0; } +static inline void __devexit omap_st_remove(struct omap_mcbsp *mcbsp) {} +#endif +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) { mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; - if (cpu_is_omap34xx()) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { /* * Initially configure the maximum thresholds to a safe value. * The McBSP FIFO usage with these values should not go under @@ -1771,26 +1783,26 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) if (omap_additional_add(mcbsp->dev)) dev_warn(mcbsp->dev, "Unable to create additional controls\n"); + } else { + mcbsp->max_tx_thres = -EINVAL; + mcbsp->max_rx_thres = -EINVAL; + } + if (cpu_is_omap34xx()) { if (mcbsp->id == 2 || mcbsp->id == 3) if (omap_st_add(mcbsp)) dev_warn(mcbsp->dev, "Unable to create sidetone controls\n"); - - } else { - mcbsp->max_tx_thres = -EINVAL; - mcbsp->max_rx_thres = -EINVAL; } } static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) { - if (cpu_is_omap34xx()) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) omap_additional_remove(mcbsp->dev); - + if (cpu_is_omap34xx()) if (mcbsp->id == 2 || mcbsp->id == 3) omap_st_remove(mcbsp); - } } #else static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} diff --git a/arch/arm/plat-omap/omap-pm-helper.c b/arch/arm/plat-omap/omap-pm-helper.c new file mode 100644 index 0000000..0f71c45 --- /dev/null +++ b/arch/arm/plat-omap/omap-pm-helper.c @@ -0,0 +1,321 @@ +/* + * omap-pm.c - OMAP power management interface + * + * Copyright (C) 2008-2011 Texas Instruments, Inc. + * Copyright (C) 2008-2009 Nokia Corporation + * Vishwanath BS + * + * This code is based on plat-omap/omap-pm-noop.c. + * + * Interface developed by (in alphabetical order): + * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan + * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff + */ + +#undef DEBUG + +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/list.h> + +/* Interface documentation is in mach/omap-pm.h */ +#include <plat/omap-pm.h> +#include <plat/omap_device.h> +#include <plat/common.h> +#include "../mach-omap2/powerdomain.h" +#include "omap-pm-helper.h" + +struct omap_opp *dsp_opps; +struct omap_opp *mpu_opps; +struct omap_opp *l3_opps; + +static DEFINE_MUTEX(bus_tput_mutex); +static DEFINE_MUTEX(mpu_tput_mutex); +static DEFINE_MUTEX(mpu_lat_mutex); + +/* Used to model a Interconnect Throughput */ +static struct interconnect_tput { + /* Total no of users at any point of interconnect */ + u8 no_of_users; + /* List of all the current users for interconnect */ + struct list_head users_list; + struct list_head node; + /* Protect interconnect throughput */ + struct mutex throughput_mutex; + /* Target level for interconnect throughput */ + unsigned long target_level; + +} *bus_tput; + +/* Used to represent a user of a interconnect throughput */ +struct users { + /* Device pointer used to uniquely identify the user */ + struct device *dev; + struct list_head node; + /* Current level as requested for interconnect throughput by the user */ + u32 level; +}; + +/* Private/Internal Functions */ + +/** + * user_lookup - look up a user by its device pointer, return a pointer + * @dev: The device to be looked up + * + * Looks for a interconnect user by its device pointer. Returns a + * pointer to + * the struct users if found, else returns NULL. + */ +static struct users *user_lookup(struct device *dev) +{ + struct users *usr, *tmp_usr; + + usr = NULL; + list_for_each_entry(tmp_usr, &bus_tput->users_list, node) { + if (tmp_usr->dev == dev) { + usr = tmp_usr; + break; + } + } + + return usr; +} + +/** + * get_user - gets a new users_list struct dynamically + * + * This function allocates dynamcially the user node + * Returns a pointer to users struct on success. On dynamic allocation + * failure + * returns a ERR_PTR(-ENOMEM). + */ +static struct users *get_user(void) +{ + struct users *user; + + user = kmalloc(sizeof(struct users), GFP_KERNEL); + if (!user) { + pr_err("%s FATAL ERROR: kmalloc failed\n", __func__); + return ERR_PTR(-ENOMEM); + } + return user; +} + +/** + * omap_bus_tput_init - Initializes the interconnect throughput + * userlist + * Allocates memory for global throughput variable dynamically. + * Intializes Userlist, no. of users and throughput target level. + * Returns 0 on sucess, else returns EINVAL if memory + * allocation fails. + */ +static int __init omap_bus_tput_init(void) +{ + bus_tput = kmalloc(sizeof(struct interconnect_tput), GFP_KERNEL); + if (!bus_tput) { + pr_err("%s FATAL ERROR: kmalloc failed\n", __func__); + return -EINVAL; + } + INIT_LIST_HEAD(&bus_tput->users_list); + mutex_init(&bus_tput->throughput_mutex); + bus_tput->no_of_users = 0; + bus_tput->target_level = 0; + return 0; +} + +/** + * add_req_tput - Request for a required level by a device + * @dev: Uniquely identifes the caller + * @level: The requested level for the interconnect bandwidth in KiB/s + * + * This function recomputes the target level of the interconnect + * bandwidth + * based on the level requested by all the users. + * Multiple calls to this function by the same device will + * replace the previous level requested + * Returns the updated level of interconnect throughput. + * In case of Invalid dev or user pointer, it returns 0. + */ +static unsigned long add_req_tput(struct device *dev, unsigned long level) +{ + int ret; + struct users *user; + + if (!dev) { + pr_err("Invalid dev pointer\n"); + ret = 0; + } + mutex_lock(&bus_tput->throughput_mutex); + user = user_lookup(dev); + if (user == NULL) { + user = get_user(); + if (IS_ERR(user)) { + pr_err("Couldn't get user from the list to" + "add new throughput constraint"); + ret = 0; + goto unlock; + } + bus_tput->target_level += level; + bus_tput->no_of_users++; + user->dev = dev; + list_add(&user->node, &bus_tput->users_list); + user->level = level; + } else { + bus_tput->target_level -= user->level; + bus_tput->target_level += level; + user->level = level; + } + ret = bus_tput->target_level; +unlock: + mutex_unlock(&bus_tput->throughput_mutex); + return ret; +} + +/** + * remove_req_tput - Release a previously requested level of + * a throughput level for interconnect + * @dev: Device pointer to dev + * + * This function recomputes the target level of the interconnect + * throughput after removing + * the level requested by the user. + * Returns 0, if the dev structure is invalid + * else returns modified interconnect throughput rate. + */ +static unsigned long remove_req_tput(struct device *dev) +{ + struct users *user; + int found = 0; + int ret; + + mutex_lock(&bus_tput->throughput_mutex); + list_for_each_entry(user, &bus_tput->users_list, node) { + if (user->dev == dev) { + found = 1; + break; + } + } + if (!found) { + /* No such user exists */ + pr_err("Invalid Device Structure\n"); + ret = 0; + goto unlock; + } + bus_tput->target_level -= user->level; + bus_tput->no_of_users--; + list_del(&user->node); + kfree(user); + ret = bus_tput->target_level; +unlock: + mutex_unlock(&bus_tput->throughput_mutex); + return ret; +} + +int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) +{ + + int ret = 0; + struct device *l3_dev; + + /* + * TODO: This will go away when complete device scaling support for + * L3 is added. + */ +#if 0 + static struct device dummy_l3_dev; +#endif + unsigned long target_level = 0; + + mutex_lock(&bus_tput_mutex); + + l3_dev = omap2_get_l3_device(); + if (!l3_dev) { + pr_err("Unable to get l3 device pointer"); + ret = -EINVAL; + goto unlock; + } + + if (r == -1) + target_level = remove_req_tput(dev); + else + target_level = add_req_tput(dev, r); + + /* Convert the throughput(in KiB/s) into Hz. */ + target_level = (target_level * 1000) / 4; + + /* + * TODO: This will go away when complete device scaling support for + * L3 is added. + */ +#if 0 + ret = omap_device_scale(&dummy_l3_dev, l3_dev, target_level); + if (ret) + pr_err("Failed: change interconnect bandwidth to %ld\n", + target_level); +#else + WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); +#endif +unlock: + mutex_unlock(&bus_tput_mutex); + return ret; +} + +int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t) +{ + struct omap_device *odev; + struct powerdomain *pwrdm_dev; + struct platform_device *pdev; + int ret = 0; + + if (!req_dev || !dev || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + /* Look for the devices Power Domain */ + pdev = container_of(dev, struct platform_device, dev); + + /* Try to catch non platform devices. */ + if (pdev->name == NULL) { + pr_err("OMAP-PM: Error: platform device not valid\n"); + return -EINVAL; + } + + odev = to_omap_device(pdev); + if (odev) { + pwrdm_dev = omap_device_get_pwrdm(odev); + } else { + pr_err("OMAP-PM: Error: Could not find omap_device for %s\n", + pdev->name); + return -EINVAL; + } + + /* Catch devices with undefined powerdomains. */ + if (!pwrdm_dev) { + pr_err("OMAP-PM: Error: could not find parent pwrdm for %s\n", + pdev->name); + return -EINVAL; + } + + if (t == -1) + ret = pwrdm_wakeuplat_release_constraint(pwrdm_dev, req_dev); + else + ret = pwrdm_wakeuplat_set_constraint(pwrdm_dev, req_dev, t); + + return ret; +} + +/* Must be called after clock framework is initialized */ +int __init omap_pm_if_init_helper(void) +{ + int ret; + ret = omap_bus_tput_init(); + if (ret) + pr_err("Failed: init of interconnect bandwidth users list\n"); + return ret; +} diff --git a/arch/arm/plat-omap/omap-pm-helper.h b/arch/arm/plat-omap/omap-pm-helper.h new file mode 100644 index 0000000..9c4b5d7 --- /dev/null +++ b/arch/arm/plat-omap/omap-pm-helper.h @@ -0,0 +1,40 @@ +/* + * OMAP PM interface helpers + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __OMAP_PM_HELPER_INTERFACE_H__ +#define __OMAP_PM_HELPER_INTERFACE_H__ + +#ifdef CONFIG_OMAP_PM +int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r); +int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t); +int __init omap_pm_if_init_helper(void); + +#else +static inline int omap_pm_set_min_bus_tput_helper(struct device *dev, + u8 agent_id, long r) +{ + return 0; +} + +static inline int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t) +{ + return 0; +} + +static inline int omap_pm_if_init_helper(void) +{ + return 0; +} +#endif /* CONFIG_OMAP_PM */ + +#endif /* __OMAP_PM_HELPER_INTERFACE_H__ */ diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c new file mode 100644 index 0000000..67319a7 --- /dev/null +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -0,0 +1,239 @@ +/* + * omap-pm-interface.c - OMAP power management interface + * + * This code implements the OMAP power management interface to + * drivers, CPUIdle, CPUFreq, and DSP Bridge. + * + * Copyright (C) 2008-2011 Texas Instruments, Inc. + * Copyright (C) 2008-2009 Nokia Corporation + * Paul Walmsley + * + * Interface developed by (in alphabetical order): + * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan + * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff + */ + +#undef DEBUG + +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <linux/device.h> +#include <linux/platform_device.h> + +/* Interface documentation is in mach/omap-pm.h */ +#include <plat/omap-pm.h> +#include <plat/omap_device.h> + +#include "omap-pm-helper.h" + +static bool off_mode_enabled; + +/* + * Device-driver-originated constraints (via board-*.c files) + * WARNING: Device drivers need to now use pm_qos directly. + */ +int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, + long t) +{ + WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", + __func__); + + return -EINVAL; +} + +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) +{ + int ret; + if (!dev || (agent_id != OCP_INITIATOR_AGENT && + agent_id != OCP_TARGET_AGENT)) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + if (r == -1) + pr_debug("OMAP PM: remove min bus tput constraint: " + "dev %s for agent_id %d\n", dev_name(dev), agent_id); + else + pr_debug("OMAP PM: add min bus tput constraint: " + "dev %s for agent_id %d: rate %ld KiB\n", + dev_name(dev), agent_id, r); + + ret = omap_pm_set_min_bus_tput_helper(dev, agent_id, r); + + return ret; +} + +int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, + long t) +{ + int ret; + if (!req_dev || !dev || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + if (t == -1) + pr_debug("OMAP PM: remove max device latency constraint: " + "dev %s\n", dev_name(dev)); + else + pr_debug("OMAP PM: add max device latency constraint: " + "dev %s, t = %ld usec\n", dev_name(dev), t); + + ret = omap_pm_set_max_dev_wakeup_lat_helper(req_dev, dev, t); + + return ret; +} + +/* WARNING: Device drivers need to now use pm_qos directly. */ +int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) +{ + WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", + __func__); + + return -EINVAL; +} + +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return -EINVAL; +} + +/* + * DSP Bridge-specific constraints + * WARNING: Device drivers need to now use opp layer/omap_device_scale directly. + */ +const struct omap_opp *omap_pm_dsp_get_opp_table(void) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return ERR_PTR(-EINVAL); +} + +void omap_pm_dsp_set_min_opp(u8 opp_id) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return; +} + +int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) +{ + WARN(1, "Deprecated %s: Driver should NOT use this function\n", + __func__); + + return -EINVAL; + +} + +EXPORT_SYMBOL(omap_pm_set_min_mpu_freq); + +u8 omap_pm_dsp_get_opp(void) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return 0; +} + +/* + * CPUFreq-originated constraint + * + * In the future, this should be handled by custom OPP clocktype + * functions. + */ + +struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return ERR_PTR(-EINVAL); +} + +void omap_pm_cpu_set_freq(unsigned long f) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return; +} + +unsigned long omap_pm_cpu_get_freq(void) +{ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + + return 0; +} + +/** + * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled + * + * Intended for use only by OMAP PM core code to notify this layer + * that off mode has been enabled. + */ +void omap_pm_enable_off_mode(void) +{ + off_mode_enabled = true; +} + +/** + * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled + * + * Intended for use only by OMAP PM core code to notify this layer + * that off mode has been disabled. + */ +void omap_pm_disable_off_mode(void) +{ + off_mode_enabled = false; +} + +/* + * Device context loss tracking + * WARNING: at this point we dont have a reliable context loss reporting + * mechanism. Instead, we ensure that we report context loss always. + */ +int omap_pm_get_dev_context_loss_count(struct device *dev) +{ + static u32 count = 1; + + if (!dev) { + WARN_ON(1); + return -EINVAL; + }; + + count++; + + /* + * Context loss count has to be a non-negative value. + * Clear the sign bit to get a value range from 0 to + * INT_MAX. Roll over to 1 + */ + count = (count & ~INT_MAX) ? 1 : count; + + pr_debug("OMAP PM: returning context loss count for dev %s count %ul\n", + dev_name(dev), count); + return count; +} + +/* Should be called before clk framework init */ +int __init omap_pm_if_early_init(void) +{ + return 0; +} + +/* Must be called after clock framework is initialized */ +int __init omap_pm_if_init(void) +{ + return omap_pm_if_init_helper(); +} + +void omap_pm_if_exit(void) +{ + /* Deallocate CPUFreq frequency table here */ +} diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c deleted file mode 100644 index 3dc3801..0000000 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * omap-pm-noop.c - OMAP power management interface - dummy version - * - * This code implements the OMAP power management interface to - * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for - * debug/demonstration use, as it does nothing but printk() whenever a - * function is called (when DEBUG is defined, below) - * - * Copyright (C) 2008-2009 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation - * Paul Walmsley - * - * Interface developed by (in alphabetical order): - * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan - * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff - */ - -#undef DEBUG - -#include <linux/init.h> -#include <linux/cpufreq.h> -#include <linux/device.h> -#include <linux/platform_device.h> - -/* Interface documentation is in mach/omap-pm.h */ -#include <plat/omap-pm.h> -#include <plat/omap_device.h> - -static bool off_mode_enabled; -static int dummy_context_loss_counter; - -/* - * Device-driver-originated constraints (via board-*.c files) - */ - -int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) -{ - if (!dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max MPU wakeup latency constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add max MPU wakeup latency constraint: " - "dev %s, t = %ld usec\n", dev_name(dev), t); - - /* - * For current Linux, this needs to map the MPU to a - * powerdomain, then go through the list of current max lat - * constraints on the MPU and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) -{ - if (!dev || (agent_id != OCP_INITIATOR_AGENT && - agent_id != OCP_TARGET_AGENT)) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (r == 0) - pr_debug("OMAP PM: remove min bus tput constraint: " - "dev %s for agent_id %d\n", dev_name(dev), agent_id); - else - pr_debug("OMAP PM: add min bus tput constraint: " - "dev %s for agent_id %d: rate %ld KiB\n", - dev_name(dev), agent_id, r); - - /* - * This code should model the interconnect and compute the - * required clock frequency, convert that to a VDD2 OPP ID, then - * set the VDD2 OPP appropriately. - * - * TI CDP code can call constraint_set here on the VDD2 OPP. - */ - - return 0; -} - -int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, - long t) -{ - if (!req_dev || !dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max device latency constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add max device latency constraint: " - "dev %s, t = %ld usec\n", dev_name(dev), t); - - /* - * For current Linux, this needs to map the device to a - * powerdomain, then go through the list of current max lat - * constraints on that powerdomain and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. Conceivably, this code should also determine - * whether to actually disable the device clocks or not, - * depending on how long it takes to re-enable the clocks. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_max_sdma_lat(struct device *dev, long t) -{ - if (!dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max DMA latency constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add max DMA latency constraint: " - "dev %s, t = %ld usec\n", dev_name(dev), t); - - /* - * For current Linux PM QOS params, this code should scan the - * list of maximum CPU and DMA latencies and select the - * smallest, then set cpu_dma_latency pm_qos_param - * accordingly. - * - * For future Linux PM QOS params, with separate CPU and DMA - * latency params, this code should just set the dma_latency param. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) -{ - if (!dev || !c || r < 0) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (r == 0) - pr_debug("OMAP PM: remove min clk rate constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add min clk rate constraint: " - "dev %s, rate = %ld Hz\n", dev_name(dev), r); - - /* - * Code in a real implementation should keep track of these - * constraints on the clock, and determine the highest minimum - * clock rate. It should iterate over each OPP and determine - * whether the OPP will result in a clock rate that would - * satisfy this constraint (and any other PM constraint in effect - * at that time). Once it finds the lowest-voltage OPP that - * meets those conditions, it should switch to it, or return - * an error if the code is not capable of doing so. - */ - - return 0; -} - -/* - * DSP Bridge-specific constraints - */ - -const struct omap_opp *omap_pm_dsp_get_opp_table(void) -{ - pr_debug("OMAP PM: DSP request for OPP table\n"); - - /* - * Return DSP frequency table here: The final item in the - * array should have .rate = .opp_id = 0. - */ - - return NULL; -} - -void omap_pm_dsp_set_min_opp(u8 opp_id) -{ - if (opp_id == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); - - /* - * - * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we - * can just test to see which is higher, the CPU's desired OPP - * ID or the DSP's desired OPP ID, and use whichever is - * highest. - * - * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP - * rate is keyed on MPU speed, not the OPP ID. So we need to - * map the OPP ID to the MPU speed for use with clk_set_rate() - * if it is higher than the current OPP clock rate. - * - */ -} - - -u8 omap_pm_dsp_get_opp(void) -{ - pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); - - /* - * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock - * - * CDP12.14+: - * Call clk_get_rate() on the OPP custom clock, map that to an - * OPP ID using the tables defined in board-*.c/chip-*.c files. - */ - - return 0; -} - -/* - * CPUFreq-originated constraint - * - * In the future, this should be handled by custom OPP clocktype - * functions. - */ - -struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) -{ - pr_debug("OMAP PM: CPUFreq request for frequency table\n"); - - /* - * Return CPUFreq frequency table here: loop over - * all VDD1 clkrates, pull out the mpu_ck frequencies, build - * table - */ - - return NULL; -} - -void omap_pm_cpu_set_freq(unsigned long f) -{ - if (f == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", - f); - - /* - * For l-o dev tree, determine whether MPU freq or DSP OPP id - * freq is higher. Find the OPP ID corresponding to the - * higher frequency. Call clk_round_rate() and clk_set_rate() - * on the OPP custom clock. - * - * CDP should just be able to set the VDD1 OPP clock rate here. - */ -} - -unsigned long omap_pm_cpu_get_freq(void) -{ - pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); - - /* - * Call clk_get_rate() on the mpu_ck. - */ - - return 0; -} - -/** - * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been enabled. - */ -void omap_pm_enable_off_mode(void) -{ - off_mode_enabled = true; -} - -/** - * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been disabled. - */ -void omap_pm_disable_off_mode(void) -{ - off_mode_enabled = false; -} - -/* - * Device context loss tracking - */ - -#ifdef CONFIG_ARCH_OMAP2PLUS - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - int count; - - if (WARN_ON(!dev)) - return -ENODEV; - - if (dev->parent == &omap_device_parent) { - count = omap_device_get_context_loss_count(pdev); - } else { - WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device", - dev_name(dev)); - - count = dummy_context_loss_counter; - - if (off_mode_enabled) { - count++; - /* - * Context loss count has to be a non-negative value. - * Clear the sign bit to get a value range from 0 to - * INT_MAX. - */ - count &= INT_MAX; - dummy_context_loss_counter = count; - } - } - - pr_debug("OMAP PM: context loss count for dev %s = %d\n", - dev_name(dev), count); - - return count; -} - -#else - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - return dummy_context_loss_counter; -} - -#endif - -/* Should be called before clk framework init */ -int __init omap_pm_if_early_init(void) -{ - return 0; -} - -/* Must be called after clock framework is initialized */ -int __init omap_pm_if_init(void) -{ - return 0; -} - -void omap_pm_if_exit(void) -{ - /* Deallocate CPUFreq frequency table here */ -} - diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index 70b836d..92b4496 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -84,6 +84,7 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/pm_runtime.h> #include <plat/omap_device.h> #include <plat/omap_hwmod.h> @@ -145,12 +146,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) odpl->activate_lat_worst = act_lat; if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { odpl->activate_lat = act_lat; - pr_warning("omap_device: %s.%d: new worst case " + pr_debug("omap_device: %s.%d: new worst case " "activate latency %d: %llu\n", od->pdev.name, od->pdev.id, od->pm_lat_level, act_lat); } else - pr_warning("omap_device: %s.%d: activate " + pr_debug("omap_device: %s.%d: activate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id, @@ -213,12 +214,12 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) odpl->deactivate_lat_worst = deact_lat; if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { odpl->deactivate_lat = deact_lat; - pr_warning("omap_device: %s.%d: new worst case " + pr_debug("omap_device: %s.%d: new worst case " "deactivate latency %d: %llu\n", od->pdev.name, od->pdev.id, od->pm_lat_level, deact_lat); } else - pr_warning("omap_device: %s.%d: deactivate " + pr_debug("omap_device: %s.%d: deactivate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id, @@ -539,20 +540,34 @@ int omap_early_device_register(struct omap_device *od) static int _od_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); + int ret; + + ret = pm_generic_runtime_suspend(dev); + + if (!ret) + omap_device_idle(pdev); + + return ret; +} - return omap_device_idle(pdev); +static int _od_runtime_idle(struct device *dev) +{ + return pm_generic_runtime_idle(dev); } static int _od_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - return omap_device_enable(pdev); + omap_device_enable(pdev); + + return pm_generic_runtime_resume(dev); } static struct dev_power_domain omap_device_power_domain = { .ops = { .runtime_suspend = _od_runtime_suspend, + .runtime_idle = _od_runtime_idle, .runtime_resume = _od_runtime_resume, USE_PLATFORM_PM_SLEEP_OPS } diff --git a/arch/arm/plat-omap/omap_rpmsg.c b/arch/arm/plat-omap/omap_rpmsg.c new file mode 100644 index 0000000..f3edc84 --- /dev/null +++ b/arch/arm/plat-omap/omap_rpmsg.c @@ -0,0 +1,482 @@ +/* + * Remote processor messaging transport (OMAP platform-specific bits) + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * + * Authors: Ohad Ben-Cohen <ohad@wizery.com> + * Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/init.h> +#include <linux/bootmem.h> +#include <linux/virtio.h> +#include <linux/virtio_config.h> +#include <linux/virtio_ids.h> +#include <linux/interrupt.h> +#include <linux/virtio_ring.h> +#include <linux/rpmsg.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/notifier.h> +#include <linux/memblock.h> +#include <linux/remoteproc.h> +#include <asm/io.h> + +#include <plat/rpmsg.h> +#include <plat/mailbox.h> +#include <plat/dsp.h> + +struct omap_rpmsg_vproc { + struct virtio_device vdev; + unsigned int vring[2]; /* mpu owns first vring, ipu owns the 2nd */ + unsigned int buf_addr; + unsigned int buf_size; /* must be page-aligned */ + void *buf_mapped; + char *mbox_name; + char *rproc_name; + struct omap_mbox *mbox; + struct rproc *rproc; + struct notifier_block nb; + struct virtqueue *vq[2]; + int base_vq_id; + int num_of_vqs; + struct rpmsg_channel_info *hardcoded_chnls; +}; + +#define to_omap_rpdev(vd) container_of(vd, struct omap_rpmsg_vproc, vdev) + +struct omap_rpmsg_vq_info { + __u16 num; /* number of entries in the virtio_ring */ + __u16 vq_id; /* a globaly unique index of this virtqueue */ + void *addr; /* address where we mapped the virtio ring */ + struct omap_rpmsg_vproc *rpdev; +}; + +/* + * For now, allocate 256 buffers of 512 bytes for each side. each buffer + * will then have 16B for the msg header and 496B for the payload. + * This will require a total space of 256KB for the buffers themselves, and + * 3 pages for every vring (the size of the vring depends on the number of + * buffers it supports). + */ +#define RPMSG_NUM_BUFS (512) +#define RPMSG_BUF_SIZE (512) +#define RPMSG_BUFS_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE) + +/* + * The alignment between the consumer and producer parts of the vring. + * Note: this is part of the "wire" protocol. If you change this, you need + * to update your BIOS image as well + */ +#define RPMSG_VRING_ALIGN (4096) + +/* With 256 buffers, our vring will occupy 3 pages */ +#define RPMSG_RING_SIZE ((DIV_ROUND_UP(vring_size(RPMSG_NUM_BUFS / 2, \ + RPMSG_VRING_ALIGN), PAGE_SIZE)) * PAGE_SIZE) + +/* The total IPC space needed to communicate with a remote processor */ +#define RPMSG_IPC_MEM (RPMSG_BUFS_SPACE + 2 * RPMSG_RING_SIZE) + +/* provide drivers with platform-specific details */ +static void omap_rpmsg_get(struct virtio_device *vdev, unsigned int request, + void *buf, unsigned len) +{ + struct omap_rpmsg_vproc *rpdev = to_omap_rpdev(vdev); + void *presult; + int iresult; + + switch (request) { + case VPROC_BUF_ADDR: + /* user data is at stake so bugs here cannot be tolerated */ + BUG_ON(len != sizeof(rpdev->buf_mapped)); + memcpy(buf, &rpdev->buf_mapped, len); + break; + case VPROC_SIM_BASE: + /* user data is at stake so bugs here cannot be tolerated */ + BUG_ON(len != sizeof(presult)); + /* + * calculate a simulated base address to make virtio's + * virt_to_page() happy. + */ + presult = __va(rpdev->buf_addr); + memcpy(buf, &presult, len); + break; + case VPROC_BUF_NUM: + /* user data is at stake so bugs here cannot be tolerated */ + BUG_ON(len != sizeof(iresult)); + iresult = RPMSG_NUM_BUFS; + memcpy(buf, &iresult, len); + break; + case VPROC_BUF_SZ: + /* user data is at stake so bugs here cannot be tolerated */ + BUG_ON(len != sizeof(iresult)); + iresult = RPMSG_BUF_SIZE; + memcpy(buf, &iresult, len); + break; + case VPROC_STATIC_CHANNELS: + /* user data is at stake so bugs here cannot be tolerated */ + BUG_ON(len != sizeof(rpdev->hardcoded_chnls)); + memcpy(buf, &rpdev->hardcoded_chnls, len); + break; + default: + dev_err(&vdev->dev, "invalid request: %d\n", request); + } +} + +/* kick the remote processor, and let it know which virtqueue to poke at */ +static void omap_rpmsg_notify(struct virtqueue *vq) +{ + struct omap_rpmsg_vq_info *rpvq = vq->priv; + int ret; + + pr_debug("sending mailbox msg: %d\n", rpvq->vq_id); + /* send the index of the triggered virtqueue as the mailbox payload */ + ret = omap_mbox_msg_send(rpvq->rpdev->mbox, rpvq->vq_id); + if (ret) + pr_err("ugh, omap_mbox_msg_send() failed: %d\n", ret); +} + +static int omap_rpmsg_mbox_callback(struct notifier_block *this, + unsigned long index, void *data) +{ + mbox_msg_t msg = (mbox_msg_t) data; + struct omap_rpmsg_vproc *rpdev; + + rpdev = container_of(this, struct omap_rpmsg_vproc, nb); + + pr_debug("mbox msg: 0x%x\n", msg); + + switch (msg) { + case RP_MBOX_CRASH: + pr_err("%s has just crashed !\n", rpdev->rproc_name); + /* todo: smarter error handling here */ + break; + case RP_MBOX_ECHO_REPLY: + pr_info("received echo reply from %s !\n", rpdev->rproc_name); + break; + case RP_MBOX_PENDING_MSG: + /* + * a new inbound message is waiting in our own vring (index 0). + * Let's pretend the message explicitly contained the vring + * index number and handle it generically + */ + msg = rpdev->base_vq_id; + /* intentional fall-through */ + default: + /* ignore vq indices which are clearly not for us */ + if (msg < rpdev->base_vq_id) + break; + + msg -= rpdev->base_vq_id; + + /* + * Currently both PENDING_MSG and explicit-virtqueue-index + * messaging are supported. + * Whatever approach is taken, at this point 'msg' contains + * the index of the vring which was just triggered. + */ + if (msg < rpdev->num_of_vqs) + vring_interrupt(msg, rpdev->vq[msg]); + } + + return NOTIFY_DONE; +} + +static struct virtqueue *rp_find_vq(struct virtio_device *vdev, + unsigned index, + void (*callback)(struct virtqueue *vq), + const char *name) +{ + struct omap_rpmsg_vproc *rpdev = to_omap_rpdev(vdev); + struct omap_rpmsg_vq_info *rpvq; + struct virtqueue *vq; + int err; + + rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL); + if (!rpvq) + return ERR_PTR(-ENOMEM); + + /* ioremap'ing normal memory, so we cast away sparse's complaints */ + rpvq->addr = (__force void *) ioremap_nocache(rpdev->vring[index], + RPMSG_RING_SIZE); + if (!rpvq->addr) { + err = -ENOMEM; + goto free_rpvq; + } + + memset(rpvq->addr, 0, RPMSG_RING_SIZE); + + pr_debug("vring%d: phys 0x%x, virt 0x%x\n", index, rpdev->vring[index], + (unsigned int) rpvq->addr); + + vq = vring_new_virtqueue(RPMSG_NUM_BUFS / 2, RPMSG_VRING_ALIGN, vdev, + rpvq->addr, omap_rpmsg_notify, callback, name); + if (!vq) { + pr_err("vring_new_virtqueue failed\n"); + err = -ENOMEM; + goto unmap_vring; + } + + rpdev->vq[index] = vq; + vq->priv = rpvq; + /* system-wide unique id for this virtqueue */ + rpvq->vq_id = rpdev->base_vq_id + index; + rpvq->rpdev = rpdev; + + return vq; + +unmap_vring: + /* iounmap normal memory, so make sparse happy */ + iounmap((__force void __iomem *) rpvq->addr); +free_rpvq: + kfree(rpvq); + return ERR_PTR(err); +} + +static void omap_rpmsg_del_vqs(struct virtio_device *vdev) +{ + struct virtqueue *vq, *n; + struct omap_rpmsg_vproc *rpdev = to_omap_rpdev(vdev); + + list_for_each_entry_safe(vq, n, &vdev->vqs, list) { + struct omap_rpmsg_vq_info *rpvq = vq->priv; + vring_del_virtqueue(vq); + kfree(rpvq); + } + + if (rpdev->mbox) + omap_mbox_put(rpdev->mbox, &rpdev->nb); + + if (rpdev->rproc) + rproc_put(rpdev->rproc); +} + +static int omap_rpmsg_find_vqs(struct virtio_device *vdev, unsigned nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char *names[]) +{ + struct omap_rpmsg_vproc *rpdev = to_omap_rpdev(vdev); + int i, err; + + /* we maintain two virtqueues per remote processor (for RX and TX) */ + if (nvqs != 2) + return -EINVAL; + + for (i = 0; i < nvqs; ++i) { + vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto error; + } + } + + rpdev->num_of_vqs = nvqs; + + /* ioremap'ing normal memory, so we cast away sparse's complaints */ + rpdev->buf_mapped = (__force void *) ioremap_nocache(rpdev->buf_addr, + rpdev->buf_size); + if (!rpdev->buf_mapped) { + pr_err("ioremap failed\n"); + err = -ENOMEM; + goto error; + } + + /* for now, use mailbox's notifiers. later that can be optimized */ + rpdev->nb.notifier_call = omap_rpmsg_mbox_callback; + rpdev->mbox = omap_mbox_get(rpdev->mbox_name, &rpdev->nb); + if (IS_ERR(rpdev->mbox)) { + pr_err("failed to get mailbox %s\n", rpdev->mbox_name); + err = -EINVAL; + goto unmap_buf; + } + + pr_debug("buf: phys 0x%x, virt 0x%x\n", rpdev->buf_addr, + (unsigned int) rpdev->buf_mapped); + + /* tell the M3 we're ready. hmm. do we really need this msg */ + err = omap_mbox_msg_send(rpdev->mbox, RP_MBOX_READY); + if (err) { + pr_err("ugh, omap_mbox_msg_send() failed: %d\n", err); + goto put_mbox; + } + + /* send it the physical address of the mapped buffer + vrings, */ + /* this should be moved to the resource table logic */ + err = omap_mbox_msg_send(rpdev->mbox, (mbox_msg_t) rpdev->buf_addr); + if (err) { + pr_err("ugh, omap_mbox_msg_send() failed: %d\n", err); + goto put_mbox; + } + + /* ping the remote processor. this is only for sanity-sake; + * there is no functional effect whatsoever */ + err = omap_mbox_msg_send(rpdev->mbox, RP_MBOX_ECHO_REQUEST); + if (err) { + pr_err("ugh, omap_mbox_msg_send() failed: %d\n", err); + goto put_mbox; + } + + /* now load the firmware, and take the M3 out of reset */ + rpdev->rproc = rproc_get(rpdev->rproc_name); + if (!rpdev->rproc) { + pr_err("failed to get rproc %s\n", rpdev->rproc_name); + err = -EINVAL; + } + + return 0; + +put_mbox: + omap_mbox_put(rpdev->mbox, &rpdev->nb); +unmap_buf: + /* iounmap normal memory, so make sparse happy */ + iounmap((__force void __iomem *)rpdev->buf_mapped); +error: + omap_rpmsg_del_vqs(vdev); + return err; +} + +/* + * should be nice to add firmware support for these handlers. + * for now provide them so virtio doesn't crash + */ +static u8 omap_rpmsg_get_status(struct virtio_device *vdev) +{ + return 0; +} + +static void omap_rpmsg_set_status(struct virtio_device *vdev, u8 status) +{ + dev_dbg(&vdev->dev, "new status: %d\n", status); +} + +static void omap_rpmsg_reset(struct virtio_device *vdev) +{ + dev_dbg(&vdev->dev, "reset !\n"); +} + +static u32 omap_rpmsg_get_features(struct virtio_device *vdev) +{ + /* for now, use hardcoded bitmap. later this should be provided + * by the firmware itself */ + return (1 << VIRTIO_RPMSG_F_NS); +} + +static void omap_rpmsg_finalize_features(struct virtio_device *vdev) +{ + /* Give virtio_ring a chance to accept features */ + vring_transport_features(vdev); +} + +static void omap_rpmsg_vproc_release(struct device *dev) +{ + /* this handler is provided so driver core doesn't yell at us */ +} + +static struct virtio_config_ops omap_rpmsg_config_ops = { + .get_features = omap_rpmsg_get_features, + .finalize_features = omap_rpmsg_finalize_features, + .get = omap_rpmsg_get, + .find_vqs = omap_rpmsg_find_vqs, + .del_vqs = omap_rpmsg_del_vqs, + .reset = omap_rpmsg_reset, + .set_status = omap_rpmsg_set_status, + .get_status = omap_rpmsg_get_status, +}; + +static struct rpmsg_channel_info omap_ipuc0_hardcoded_chnls[] = { + { "rpmsg-resmgr", 100, RPMSG_ADDR_ANY }, + { "rpmsg-server-sample", 137, RPMSG_ADDR_ANY }, + { }, +}; + +static struct rpmsg_channel_info omap_ipuc1_hardcoded_chnls[] = { + { "rpmsg-resmgr", 100, RPMSG_ADDR_ANY }, + { }, +}; + +static struct omap_rpmsg_vproc omap_rpmsg_vprocs[] = { + /* ipu_c0's rpmsg backend */ + { + .vdev.id.device = VIRTIO_ID_RPMSG, + .vdev.config = &omap_rpmsg_config_ops, + .mbox_name = "mailbox-1", + .rproc_name = "ipu", + .base_vq_id = 0, + .hardcoded_chnls = omap_ipuc0_hardcoded_chnls, + }, + /* ipu_c1's rpmsg backend */ + { + .vdev.id.device = VIRTIO_ID_RPMSG, + .vdev.config = &omap_rpmsg_config_ops, + .mbox_name = "mailbox-1", + .rproc_name = "ipu", + .base_vq_id = 2, + .hardcoded_chnls = omap_ipuc1_hardcoded_chnls, + }, +}; + +static int __init omap_rpmsg_ini(void) +{ + int i, ret = 0; + phys_addr_t paddr = omap_dsp_get_mempool_base(); + phys_addr_t psize = omap_dsp_get_mempool_size(); + + for (i = 0; i < ARRAY_SIZE(omap_rpmsg_vprocs); i++) { + struct omap_rpmsg_vproc *rpdev = &omap_rpmsg_vprocs[i]; + + if (psize < RPMSG_IPC_MEM) { + pr_err("out of carveout memory: %d (%d)\n", psize, i); + return -ENOMEM; + } + + rpdev->buf_addr = paddr; + rpdev->buf_size = RPMSG_BUFS_SPACE; + rpdev->vring[0] = paddr + RPMSG_BUFS_SPACE; + rpdev->vring[1] = paddr + RPMSG_BUFS_SPACE + RPMSG_RING_SIZE; + + paddr += RPMSG_IPC_MEM; + psize -= RPMSG_IPC_MEM; + + pr_debug("rpdev%d: buf 0x%x, vring0 0x%x, vring1 0x%x\n", i, + rpdev->buf_addr, rpdev->vring[0], rpdev->vring[1]); + + rpdev->vdev.dev.release = omap_rpmsg_vproc_release; + + ret = register_virtio_device(&rpdev->vdev); + if (ret) { + pr_err("failed to register rpdev: %d\n", ret); + break; + } + } + + return ret; +} +module_init(omap_rpmsg_ini); + +static void __exit omap_rpmsg_fini(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(omap_rpmsg_vprocs); i++) { + struct omap_rpmsg_vproc *rpdev = &omap_rpmsg_vprocs[i]; + + unregister_virtio_device(&rpdev->vdev); + } +} +module_exit(omap_rpmsg_fini); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("OMAP Remote processor messaging virtio device"); diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index a3f50b3..6af3d0b 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -166,7 +166,7 @@ static void __init omap_detect_sram(void) else if (cpu_is_omap1611()) omap_sram_size = SZ_256K; else { - printk(KERN_ERR "Could not detect SRAM size\n"); + pr_err("Could not detect SRAM size\n"); omap_sram_size = 0x4000; } } @@ -221,10 +221,10 @@ static void __init omap_map_sram(void) omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE); iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); - printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", - __pfn_to_phys(omap_sram_io_desc[0].pfn), - omap_sram_io_desc[0].virtual, - omap_sram_io_desc[0].length); + pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n", + (long long) __pfn_to_phys(omap_sram_io_desc[0].pfn), + omap_sram_io_desc[0].virtual, + omap_sram_io_desc[0].length); /* * Normally devicemaps_init() would flush caches and tlb after @@ -252,7 +252,7 @@ static void __init omap_map_sram(void) void *omap_sram_push_address(unsigned long size) { if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) { - printk(KERN_ERR "Not enough space in SRAM\n"); + pr_err("Not enough space in SRAM\n"); return NULL; } diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index c10d10c..2abf966 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1199,7 +1199,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); #ifdef CONFIG_PM -static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp) +static void s3c2410_dma_suspend_chan(struct s3c2410_dma_chan *cp) { printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 9aee7e1..fc8c5f8 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/irq.h> #include <asm/mach/irq.h> @@ -668,3 +669,8 @@ void __init s3c24xx_init_irq(void) irqdbf("s3c2410: registered interrupt handlers\n"); } + +struct syscore_ops s3c24xx_irq_syscore_ops = { + .suspend = s3c24xx_irq_suspend, + .resume = s3c24xx_irq_resume, +}; diff --git a/arch/arm/plat-s5p/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c index 6db9262..20336c8 100644 --- a/arch/arm/plat-s5p/dev-onenand.c +++ b/arch/arm/plat-s5p/dev-onenand.c @@ -15,8 +15,6 @@ #include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/onenand.h> #include <mach/irqs.h> #include <mach/map.h> @@ -45,13 +43,3 @@ struct platform_device s5p_device_onenand = { .num_resources = ARRAY_SIZE(s5p_onenand_resources), .resource = s5p_onenand_resources, }; - -void s5p_onenand_set_platdata(struct onenand_platform_data *pdata) -{ - struct onenand_platform_data *pd; - - pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); - if (!pd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s5p_device_onenand.dev.platform_data = pd; -} diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index a6c3d32..d973d39 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h @@ -39,7 +39,7 @@ #define S5P_VA_TWD S5P_VA_COREPERI(0x600) #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) -#define S5P_VA_USB_HSPHY S3C_ADDR(0x02900000) +#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC0 VA_VIC(0) diff --git a/arch/arm/plat-samsung/dev-onenand.c b/arch/arm/plat-samsung/dev-onenand.c index 45ec732..f54ae71 100644 --- a/arch/arm/plat-samsung/dev-onenand.c +++ b/arch/arm/plat-samsung/dev-onenand.c @@ -13,8 +13,6 @@ #include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/onenand.h> #include <mach/irqs.h> #include <mach/map.h> @@ -43,13 +41,3 @@ struct platform_device s3c_device_onenand = { .num_resources = ARRAY_SIZE(s3c_onenand_resources), .resource = s3c_onenand_resources, }; - -void s3c_onenand_set_platdata(struct onenand_platform_data *pdata) -{ - struct onenand_platform_data *pd; - - pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); - if (!pd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s3c_device_onenand.dev.platform_data = pd; -} diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index b61b8ee..4af108f 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -75,10 +75,8 @@ extern struct platform_device s5pc100_device_spi1; extern struct platform_device s5pc100_device_spi2; extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi1; -extern struct platform_device s5p6440_device_spi0; -extern struct platform_device s5p6440_device_spi1; -extern struct platform_device s5p6450_device_spi0; -extern struct platform_device s5p6450_device_spi1; +extern struct platform_device s5p64x0_device_spi0; +extern struct platform_device s5p64x0_device_spi1; extern struct platform_device s3c_device_hwmon; |