aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/common/gic.c1
-rw-r--r--arch/arm/configs/android_4430_defconfig1926
-rw-r--r--arch/arm/configs/omap2plus_defconfig37
-rw-r--r--arch/arm/configs/panda_defconfig279
-rw-r--r--arch/arm/include/asm/dma-mapping.h15
-rw-r--r--arch/arm/include/asm/hardware/cache-l2x0.h16
-rw-r--r--arch/arm/include/asm/irq.h2
-rw-r--r--arch/arm/include/asm/mach/map.h1
-rw-r--r--arch/arm/include/asm/nmi.h14
-rw-r--r--arch/arm/include/asm/pgtable.h3
-rw-r--r--arch/arm/include/asm/proc-fns.h14
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/kernel/smp.c5
-rw-r--r--arch/arm/kernel/smp_twd.c67
-rw-r--r--arch/arm/mach-omap1/Makefile5
-rw-r--r--arch/arm/mach-omap1/dmtimer.c179
-rw-r--r--arch/arm/mach-omap1/gpio15xx.c29
-rw-r--r--arch/arm/mach-omap1/gpio16xx.c48
-rw-r--r--arch/arm/mach-omap1/gpio7xx.c41
-rw-r--r--arch/arm/mach-omap1/mailbox.c3
-rw-r--r--arch/arm/mach-omap1/omap1-cpufreq.c (renamed from arch/arm/plat-omap/cpu-omap.c)54
-rw-r--r--arch/arm/mach-omap1/timer32k.c4
-rw-r--r--arch/arm/mach-omap2/Kconfig42
-rw-r--r--arch/arm/mach-omap2/Makefile48
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c100
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c260
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c6
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c151
-rw-r--r--arch/arm/mach-omap2/clkt_dpll.c14
-rw-r--r--arch/arm/mach-omap2/clock.c24
-rw-r--r--arch/arm/mach-omap2/clock.h21
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c72
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c60
-rw-r--r--arch/arm/mach-omap2/clock34xx.c2
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c76
-rw-r--r--arch/arm/mach-omap2/clock44xx.h2
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c1314
-rw-r--r--arch/arm/mach-omap2/clockdomain.c35
-rw-r--r--arch/arm/mach-omap2/clockdomain.h3
-rw-r--r--arch/arm/mach-omap2/clockdomain2xxx_3xxx.c12
-rw-r--r--arch/arm/mach-omap2/clockdomain44xx.c16
-rw-r--r--arch/arm/mach-omap2/clockdomains44xx_data.c204
-rw-r--r--arch/arm/mach-omap2/cm-regbits-44xx.h32
-rw-r--r--arch/arm/mach-omap2/cm1_44xx.h26
-rw-r--r--arch/arm/mach-omap2/cm2_44xx.h14
-rw-r--r--arch/arm/mach-omap2/cm44xx.c322
-rw-r--r--arch/arm/mach-omap2/cm44xx.h4
-rw-r--r--arch/arm/mach-omap2/common.c1
-rw-r--r--arch/arm/mach-omap2/control.c63
-rw-r--r--arch/arm/mach-omap2/control.h23
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c5
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c747
-rw-r--r--arch/arm/mach-omap2/devices.c244
-rw-r--r--arch/arm/mach-omap2/display.c24
-rw-r--r--arch/arm/mach-omap2/dmtimer.c283
-rw-r--r--arch/arm/mach-omap2/dmtimer.h32
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c72
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c576
-rw-r--r--arch/arm/mach-omap2/dvfs.c1314
-rw-r--r--arch/arm/mach-omap2/dvfs.h47
-rw-r--r--arch/arm/mach-omap2/emif.c1514
-rw-r--r--arch/arm/mach-omap2/gpio.c73
-rw-r--r--arch/arm/mach-omap2/gpmc.c12
-rw-r--r--arch/arm/mach-omap2/hsmmc.c26
-rw-r--r--arch/arm/mach-omap2/hsmmc.h5
-rw-r--r--arch/arm/mach-omap2/id.c66
-rw-r--r--arch/arm/mach-omap2/include/mach/barriers.h48
-rw-r--r--arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h57
-rw-r--r--arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h8
-rw-r--r--arch/arm/mach-omap2/include/mach/dmm-44xx.h363
-rw-r--r--arch/arm/mach-omap2/include/mach/dmm.h164
-rw-r--r--arch/arm/mach-omap2/include/mach/emif-44xx.h526
-rw-r--r--arch/arm/mach-omap2/include/mach/emif.h268
-rw-r--r--arch/arm/mach-omap2/include/mach/id.h1
-rw-r--r--arch/arm/mach-omap2/include/mach/lpddr2-elpida.h23
-rw-r--r--arch/arm/mach-omap2/include/mach/lpddr2-jedec.h149
-rw-r--r--arch/arm/mach-omap2/include/mach/omap-wakeupgen.h41
-rw-r--r--arch/arm/mach-omap2/include/mach/omap4-common.h141
-rw-r--r--arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h36
-rw-r--r--arch/arm/mach-omap2/include/mach/tiler.h513
-rw-r--r--arch/arm/mach-omap2/io.c5
-rw-r--r--arch/arm/mach-omap2/iommu2.c31
-rw-r--r--arch/arm/mach-omap2/ldo.c333
-rw-r--r--arch/arm/mach-omap2/ldo.h113
-rw-r--r--arch/arm/mach-omap2/ldo3xxx_data.c49
-rw-r--r--arch/arm/mach-omap2/ldo4xxx_data.c60
-rw-r--r--arch/arm/mach-omap2/lpddr2_elpida_data.c111
-rw-r--r--arch/arm/mach-omap2/lpddr2_jedec_data.c132
-rw-r--r--arch/arm/mach-omap2/mailbox.c144
-rw-r--r--arch/arm/mach-omap2/mcbsp.c13
-rw-r--r--arch/arm/mach-omap2/mux.c99
-rw-r--r--arch/arm/mach-omap2/mux.h38
-rw-r--r--arch/arm/mach-omap2/omap-hotplug.c30
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c170
-rw-r--r--arch/arm/mach-omap2/omap-smp.c71
-rw-r--r--arch/arm/mach-omap2/omap-wakeupgen.c311
-rw-r--r--arch/arm/mach-omap2/omap2plus-cpufreq.c439
-rw-r--r--arch/arm/mach-omap2/omap4-common.c249
-rw-r--r--arch/arm/mach-omap2/omap4-mpuss-lowpower.c824
-rw-r--r--arch/arm/mach-omap2/omap4-sar-layout.h124
-rw-r--r--arch/arm/mach-omap2/omap4-sar.c1054
-rw-r--r--arch/arm/mach-omap2/omap44xx-smc.S24
-rw-r--r--arch/arm/mach-omap2/omap4_trim_quirks.c180
-rw-r--r--arch/arm/mach-omap2/omap_dmm.c73
-rw-r--r--arch/arm/mach-omap2/omap_fiq_debugger.c418
-rw-r--r--arch/arm/mach-omap2/omap_hsi.c426
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c184
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c19
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c19
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c350
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c1696
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.c9
-rw-r--r--arch/arm/mach-omap2/omap_l3_noc.c52
-rw-r--r--arch/arm/mach-omap2/omap_l3_noc.h79
-rw-r--r--arch/arm/mach-omap2/omap_opp_data.h28
-rw-r--r--arch/arm/mach-omap2/omap_pmic.c105
-rw-r--r--arch/arm/mach-omap2/omap_tps6236x.c434
-rw-r--r--arch/arm/mach-omap2/omap_twl.c396
-rw-r--r--arch/arm/mach-omap2/opp.c36
-rw-r--r--arch/arm/mach-omap2/opp3xxx_data.c117
-rw-r--r--arch/arm/mach-omap2/opp4xxx_data.c300
-rw-r--r--arch/arm/mach-omap2/pm-debug.c242
-rw-r--r--arch/arm/mach-omap2/pm.c272
-rw-r--r--arch/arm/mach-omap2/pm.h163
-rw-r--r--arch/arm/mach-omap2/pm24xx.c23
-rw-r--r--arch/arm/mach-omap2/pm34xx.c61
-rw-r--r--arch/arm/mach-omap2/pm44xx.c1281
-rw-r--r--arch/arm/mach-omap2/powerdomain.c250
-rw-r--r--arch/arm/mach-omap2/powerdomain.h77
-rw-r--r--arch/arm/mach-omap2/powerdomain44xx.c41
-rw-r--r--arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c2
-rw-r--r--arch/arm/mach-omap2/powerdomains2xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/powerdomains3xxx_data.c76
-rw-r--r--arch/arm/mach-omap2/powerdomains44xx_data.c184
-rw-r--r--arch/arm/mach-omap2/prcm-debug.c1688
-rw-r--r--arch/arm/mach-omap2/prcm-debug.h13
-rw-r--r--arch/arm/mach-omap2/prm-regbits-34xx.h1
-rw-r--r--arch/arm/mach-omap2/prm-regbits-44xx.h24
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.c79
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.h22
-rw-r--r--arch/arm/mach-omap2/prm44xx.c113
-rw-r--r--arch/arm/mach-omap2/prm44xx.h23
-rw-r--r--arch/arm/mach-omap2/prminst44xx.c3
-rw-r--r--arch/arm/mach-omap2/remoteproc.c164
-rw-r--r--arch/arm/mach-omap2/resetreason.c75
-rw-r--r--arch/arm/mach-omap2/resetreason.h22
-rw-r--r--arch/arm/mach-omap2/serial.c947
-rw-r--r--arch/arm/mach-omap2/sleep44xx.S695
-rw-r--r--arch/arm/mach-omap2/smartreflex-class1p5.c678
-rw-r--r--arch/arm/mach-omap2/smartreflex-class3.c30
-rw-r--r--arch/arm/mach-omap2/smartreflex.c461
-rw-r--r--arch/arm/mach-omap2/smartreflex.h61
-rw-r--r--arch/arm/mach-omap2/sr_device.c11
-rw-r--r--arch/arm/mach-omap2/temp_sensor_device.c95
-rw-r--r--arch/arm/mach-omap2/timer-gp.c16
-rw-r--r--arch/arm/mach-omap2/usb-host.c724
-rw-r--r--arch/arm/mach-omap2/usb-musb.c4
-rw-r--r--arch/arm/mach-omap2/vc.c636
-rw-r--r--arch/arm/mach-omap2/vc.h119
-rw-r--r--arch/arm/mach-omap2/vc3xxx_data.c39
-rw-r--r--arch/arm/mach-omap2/vc44xx_data.c56
-rw-r--r--arch/arm/mach-omap2/voltage.c1223
-rw-r--r--arch/arm/mach-omap2/voltage.h300
-rw-r--r--arch/arm/mach-omap2/voltagedomains2xxx_data.c32
-rw-r--r--arch/arm/mach-omap2/voltagedomains3xxx_data.c82
-rw-r--r--arch/arm/mach-omap2/voltagedomains44xx_data.c154
-rw-r--r--arch/arm/mach-omap2/vp.c426
-rw-r--r--arch/arm/mach-omap2/vp.h130
-rw-r--r--arch/arm/mach-omap2/vp3xxx_data.c36
-rw-r--r--arch/arm/mach-omap2/vp44xx_data.c56
-rw-r--r--arch/arm/mm/context.c3
-rw-r--r--arch/arm/mm/dma-mapping.c12
-rw-r--r--arch/arm/mm/mmu.c8
-rw-r--r--arch/arm/plat-omap/Kconfig73
-rw-r--r--arch/arm/plat-omap/Makefile6
-rw-r--r--arch/arm/plat-omap/clock.c46
-rw-r--r--arch/arm/plat-omap/common.c3
-rw-r--r--arch/arm/plat-omap/counter_32k.c58
-rw-r--r--arch/arm/plat-omap/devices.c111
-rw-r--r--arch/arm/plat-omap/dma.c18
-rw-r--r--arch/arm/plat-omap/dmtimer.c927
-rw-r--r--arch/arm/plat-omap/i2c.c14
-rw-r--r--arch/arm/plat-omap/include/plat/clkdev_omap.h2
-rw-r--r--arch/arm/plat-omap/include/plat/clock.h4
-rw-r--r--arch/arm/plat-omap/include/plat/common.h2
-rw-r--r--arch/arm/plat-omap/include/plat/cpu.h39
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h97
-rw-r--r--arch/arm/plat-omap/include/plat/dsp.h4
-rw-r--r--arch/arm/plat-omap/include/plat/dsscomp.h25
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h56
-rw-r--r--arch/arm/plat-omap/include/plat/gpmc.h4
-rw-r--r--arch/arm/plat-omap/include/plat/gpu.h39
-rw-r--r--arch/arm/plat-omap/include/plat/io.h4
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h13
-rw-r--r--arch/arm/plat-omap/include/plat/iommu2.h1
-rw-r--r--arch/arm/plat-omap/include/plat/irqs-44xx.h9
-rw-r--r--arch/arm/plat-omap/include/plat/irqs.h12
-rw-r--r--arch/arm/plat-omap/include/plat/mcasp.h52
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h6
-rw-r--r--arch/arm/plat-omap/include/plat/mcpdm.h28
-rw-r--r--arch/arm/plat-omap/include/plat/mcspi.h2
-rw-r--r--arch/arm/plat-omap/include/plat/mmc.h12
-rw-r--r--arch/arm/plat-omap/include/plat/omap-pm.h50
-rw-r--r--arch/arm/plat-omap/include/plat/omap-serial.h71
-rw-r--r--arch/arm/plat-omap/include/plat/omap44xx.h7
-rw-r--r--arch/arm/plat-omap/include/plat/omap_device.h2
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hsi.h494
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h26
-rw-r--r--arch/arm/plat-omap/include/plat/remoteproc.h151
-rw-r--r--arch/arm/plat-omap/include/plat/rpmsg.h68
-rw-r--r--arch/arm/plat-omap/include/plat/rpres.h57
-rw-r--r--arch/arm/plat-omap/include/plat/serial.h22
-rw-r--r--arch/arm/plat-omap/include/plat/sram.h1
-rw-r--r--arch/arm/plat-omap/include/plat/temperature_sensor.h65
-rw-r--r--arch/arm/plat-omap/include/plat/usb.h18
-rw-r--r--arch/arm/plat-omap/iommu.c184
-rw-r--r--arch/arm/plat-omap/iovmm.c4
-rw-r--r--arch/arm/plat-omap/mailbox.c43
-rw-r--r--arch/arm/plat-omap/mcbsp.c107
-rw-r--r--arch/arm/plat-omap/omap-pm-helper.c345
-rw-r--r--arch/arm/plat-omap/omap-pm-helper.h40
-rw-r--r--arch/arm/plat-omap/omap-pm-interface.c251
-rw-r--r--arch/arm/plat-omap/omap-pm-noop.c363
-rw-r--r--arch/arm/plat-omap/omap_device.c10
-rw-r--r--arch/arm/plat-omap/omap_rpmsg.c601
-rw-r--r--arch/arm/plat-omap/rproc_user.c185
-rw-r--r--arch/arm/plat-omap/sram.c67
-rw-r--r--arch/arm/vfp/vfpmodule.c29
229 files changed, 34177 insertions, 5104 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b9d6077..45e2bee 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -29,6 +29,7 @@ config ARM
select HAVE_GENERIC_HARDIRQS
select HAVE_SPARSE_IRQ
select GENERIC_IRQ_SHOW
+ select CPU_PM if (SUSPEND || CPU_IDLE)
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 4ddd0a6..be604f0 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -365,6 +365,7 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
if (gic_nr == 0)
gic_cpu_base_addr = cpu_base;
+ gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic, irq_start);
gic_cpu_init(gic);
}
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/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/panda_defconfig b/arch/arm/configs/panda_defconfig
new file mode 100644
index 0000000..b88843c
--- /dev/null
+++ b/arch/arm/configs/panda_defconfig
@@ -0,0 +1,279 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_MACH_OMAP_4430SDP is not set
+CONFIG_ARM_THUMBEE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_CMDLINE="console=ttyFIQ0"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=y
+CONFIG_WAKELOCK=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_PHONET=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_ONENAND=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+# CONFIG_ANDROID_PMEM is not set
+CONFIG_KERNEL_DEBUGGER_CORE=y
+CONFIG_UID_STAT=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_IFB=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_PPP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_HWMON is not set
+CONFIG_TWL6030_PWM=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_PVR_SGX=y
+CONFIG_PVR_NEED_PVR_DPF=y
+CONFIG_PVR_NEED_PVR_ASSERT=y
+CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y
+CONFIG_FB=y
+CONFIG_OMAP2_DSS=y
+# CONFIG_OMAP2_DSS_VENC is not set
+CONFIG_FB_OMAP2=y
+CONFIG_PANEL_GENERIC_DPI=y
+CONFIG_DISPLAY_SUPPORT=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_USB_MUSB_PERIPHERAL=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 4fff837..07f1d11 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -236,6 +236,21 @@ extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
void *, dma_addr_t, size_t);
+/**
+ * dma_alloc_stronglyordered - allocate strongly ordered memory
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @size: required memory size
+ * @handle: bus-specific address
+ *
+ * Allocate some stronly ordered memory. This function allocates pages, and
+ * will return the CPU-viewed address, and sets @handle to be the
+ * device-viewed address.
+ */
+extern void *dma_alloc_stronglyordered(struct device *, size_t, dma_addr_t *,
+ gfp_t);
+
+#define dma_free_stronglyordered(dev, size, cpu_addr, handle) \
+ dma_free_coherent(dev, size, cpu_addr, handle)
#ifdef CONFIG_DMABOUNCE
/*
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 2a20876..5dc6db1 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -45,16 +45,18 @@
#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_REV_MASK (0x3f)
@@ -62,7 +64,7 @@
#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 (0x7 << 17)
@@ -73,6 +75,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
+
#define REV_PL310_R2P0 4
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 28810c6..2faf2e0 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -3,6 +3,8 @@
#include <mach/irqs.h>
+#define ARCH_HAS_NMI_WATCHDOG
+
#ifndef irq_canonicalize
#define irq_canonicalize(i) (i)
#endif
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index d2fedb5..b36f365 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -29,6 +29,7 @@ struct map_desc {
#define MT_MEMORY_NONCACHED 11
#define MT_MEMORY_DTCM 12
#define MT_MEMORY_ITCM 13
+#define MT_MEMORY_SO 14
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
diff --git a/arch/arm/include/asm/nmi.h b/arch/arm/include/asm/nmi.h
new file mode 100644
index 0000000..3cf8bdf
--- /dev/null
+++ b/arch/arm/include/asm/nmi.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_ARM_NMI_H_
+#define __ASM_ARM_NMI_H_
+
+#include <linux/notifier.h>
+
+extern struct atomic_notifier_head touch_watchdog_notifier_head;
+
+static inline void touch_nmi_watchdog(void)
+{
+ atomic_notifier_call_chain(&touch_watchdog_notifier_head, 0, 0);
+ touch_softlockup_watchdog();
+}
+
+#endif /* __ASM_ARM_NMI_H_ */
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 6afd081..a558978 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -232,6 +232,9 @@ extern pgprot_t pgprot_kernel;
#define pgprot_writecombine(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+#define pgprot_stronglyordered(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
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/irq.c b/arch/arm/kernel/irq.c
index 83bbad0..fee2edf 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -51,6 +51,8 @@
unsigned long irq_err_count;
+ATOMIC_NOTIFIER_HEAD(touch_watchdog_notifier_head);
+
int arch_show_interrupts(struct seq_file *p, int prec)
{
#ifdef CONFIG_FIQ
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e895f97..1312861 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -279,6 +279,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
{
struct mm_struct *mm = &init_mm;
unsigned int cpu;
+ static bool booted;
/*
* The identity mapping is uncached (strongly ordered), so
@@ -310,7 +311,9 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
notify_cpu_starting(cpu);
- 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 2c277d4..350a125 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -10,13 +10,17 @@
*/
#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>
@@ -24,7 +28,9 @@
/* 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 +86,48 @@ 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_update_freq(__get_cpu_var(twd_ce), twd_timer_rate);
+}
+
+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 +172,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 +189,11 @@ 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);
- 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);
- clockevents_register_device(clk);
+ __get_cpu_var(twd_ce) = clk;
+
+ clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff);
}
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 5b114d1..19e5a82 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -4,12 +4,15 @@
# 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 pm_bus.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o dmtimer.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
diff --git a/arch/arm/mach-omap1/dmtimer.c b/arch/arm/mach-omap1/dmtimer.c
new file mode 100644
index 0000000..dbc189c
--- /dev/null
+++ b/arch/arm/mach-omap1/dmtimer.c
@@ -0,0 +1,179 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE 0xfffb1400
+#define OMAP1610_GPTIMER2_BASE 0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE 0xfffb2400
+#define OMAP1610_GPTIMER4_BASE 0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE 0xfffb3400
+#define OMAP1610_GPTIMER6_BASE 0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE 0xfffb7400
+#define OMAP1610_GPTIMER8_BASE 0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT 8
+
+#define OMAP_TIMER_OCP_CFG_REG 0x10
+#define OMAP_TIMER_SYS_STAT_REG 0x14
+#define OMAP_TIMER_IF_CTRL_REG 0x40
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+ int source)
+{
+ int n = (pdev->id - 1) << 1;
+ u32 l;
+
+ l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+ l |= source << n;
+ omap_writel(l, MOD_CONF_CTRL_1);
+
+ return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+ int i;
+ int ret;
+ struct dmtimer_platform_data *pdata;
+ struct platform_device *pdev;
+
+ if (!cpu_is_omap16xx())
+ return 0;
+
+ for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+ struct resource res[2];
+ u32 base, irq;
+
+ switch (i) {
+ case 1:
+ base = OMAP1610_GPTIMER1_BASE;
+ irq = INT_1610_GPTIMER1;
+ break;
+ case 2:
+ base = OMAP1610_GPTIMER2_BASE;
+ irq = INT_1610_GPTIMER2;
+ break;
+ case 3:
+ base = OMAP1610_GPTIMER3_BASE;
+ irq = INT_1610_GPTIMER3;
+ break;
+ case 4:
+ base = OMAP1610_GPTIMER4_BASE;
+ irq = INT_1610_GPTIMER4;
+ break;
+ case 5:
+ base = OMAP1610_GPTIMER5_BASE;
+ irq = INT_1610_GPTIMER5;
+ break;
+ case 6:
+ base = OMAP1610_GPTIMER6_BASE;
+ irq = INT_1610_GPTIMER6;
+ break;
+ case 7:
+ base = OMAP1610_GPTIMER7_BASE;
+ irq = INT_1610_GPTIMER7;
+ break;
+ case 8:
+ base = OMAP1610_GPTIMER8_BASE;
+ irq = INT_1610_GPTIMER8;
+ break;
+ default:
+ /*
+ * not supposed to reach here.
+ * this is to remove warning.
+ */
+ return -EINVAL;
+ }
+
+ pdev = platform_device_alloc("omap_timer", i);
+ if (!pdev) {
+ pr_err("%s: Failed to device alloc for dmtimer%d\n",
+ __func__, i);
+ return -ENOMEM;
+ }
+
+ memset(res, 0, 2 * sizeof(struct resource));
+ res[0].start = base;
+ res[0].end = base + 0x46;
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = irq;
+ res[1].end = irq;
+ res[1].flags = IORESOURCE_IRQ;
+ ret = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+ __func__);
+ goto err_free_pdev;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_free_pdata;
+ }
+
+ pdata->set_timer_src = omap1_dm_timer_set_src;
+ pdata->is_early_init = 0;
+ pdata->timer_ip_type = OMAP_TIMER_IP_VERSION_1;
+ pdata->needs_manual_reset = 1;
+
+ ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+ __func__);
+ goto err_free_pdata;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+ __func__);
+ goto err_free_pdata;
+ }
+
+ dev_dbg(&pdev->dev, " Registered.\n");
+ }
+
+ return 0;
+
+err_free_pdata:
+ kfree(pdata);
+
+err_free_pdev:
+ platform_device_unregister(pdev);
+
+ return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index 364137c..634903e 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -34,11 +34,23 @@ static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap15xx_mpuio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP_MPUIO_IO_CNTL,
+ .datain = OMAP_MPUIO_INPUT_LATCH,
+ .dataout = OMAP_MPUIO_OUTPUT,
+ .irqstatus = OMAP_MPUIO_GPIO_INT,
+ .irqenable = OMAP_MPUIO_GPIO_MASKIT,
+ .irqenable_inv = true,
+ .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE,
+};
+
static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
- .bank_type = METHOD_MPUIO,
+ .is_mpuio = true,
.bank_width = 16,
.bank_stride = 1,
+ .regs = &omap15xx_mpuio_regs,
};
static struct platform_device omap15xx_mpu_gpio = {
@@ -64,10 +76,22 @@ static struct __initdata resource omap15xx_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap15xx_gpio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP1510_GPIO_DIR_CONTROL,
+ .datain = OMAP1510_GPIO_DATA_INPUT,
+ .dataout = OMAP1510_GPIO_DATA_OUTPUT,
+ .irqstatus = OMAP1510_GPIO_INT_STATUS,
+ .irqenable = OMAP1510_GPIO_INT_MASK,
+ .irqenable_inv = true,
+ .irqctrl = OMAP1510_GPIO_INT_CONTROL,
+ .pinctrl = OMAP1510_GPIO_PIN_CONTROL,
+};
+
static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
.virtual_irq_start = IH_GPIO_BASE,
- .bank_type = METHOD_GPIO_1510,
.bank_width = 16,
+ .regs = &omap15xx_gpio_regs,
};
static struct platform_device omap15xx_gpio = {
@@ -93,7 +117,6 @@ static int __init omap15xx_gpio_init(void)
platform_device_register(&omap15xx_mpu_gpio);
platform_device_register(&omap15xx_gpio);
- gpio_bank_count = 2;
return 0;
}
postcore_initcall(omap15xx_gpio_init);
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index 293a246..c6a4554 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -37,11 +37,24 @@ static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap16xx_mpuio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP_MPUIO_IO_CNTL,
+ .datain = OMAP_MPUIO_INPUT_LATCH,
+ .dataout = OMAP_MPUIO_OUTPUT,
+ .irqstatus = OMAP_MPUIO_GPIO_INT,
+ .irqenable = OMAP_MPUIO_GPIO_MASKIT,
+ .irqenable_inv = true,
+ .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE,
+};
+
static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
- .bank_type = METHOD_MPUIO,
+ .is_mpuio = true,
.bank_width = 16,
.bank_stride = 1,
+ .suspend_support = true,
+ .regs = &omap16xx_mpuio_regs,
};
static struct platform_device omap16xx_mpu_gpio = {
@@ -67,10 +80,30 @@ static struct __initdata resource omap16xx_gpio1_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap16xx_gpio_regs = {
+ .revision = OMAP1610_GPIO_REVISION,
+ .direction = OMAP1610_GPIO_DIRECTION,
+ .set_dataout = OMAP1610_GPIO_SET_DATAOUT,
+ .clr_dataout = OMAP1610_GPIO_CLEAR_DATAOUT,
+ .datain = OMAP1610_GPIO_DATAIN,
+ .dataout = OMAP1610_GPIO_DATAOUT,
+ .irqstatus = OMAP1610_GPIO_IRQSTATUS1,
+ .irqenable = OMAP1610_GPIO_IRQENABLE1,
+ .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1,
+ .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1,
+ .wkup_status = OMAP1610_GPIO_WAKEUPENABLE,
+ .wkup_clear = OMAP1610_GPIO_CLEAR_WAKEUPENA,
+ .wkup_set = OMAP1610_GPIO_SET_WAKEUPENA,
+ .edgectrl1 = OMAP1610_GPIO_EDGE_CTRL1,
+ .edgectrl2 = OMAP1610_GPIO_EDGE_CTRL2,
+ .sysconfig = OMAP1610_GPIO_SYSCONFIG,
+};
+
static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
.virtual_irq_start = IH_GPIO_BASE,
- .bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .suspend_support = true,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio1 = {
@@ -98,8 +131,9 @@ static struct __initdata resource omap16xx_gpio2_resources[] = {
static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
.virtual_irq_start = IH_GPIO_BASE + 16,
- .bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .suspend_support = true,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio2 = {
@@ -127,8 +161,9 @@ static struct __initdata resource omap16xx_gpio3_resources[] = {
static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
.virtual_irq_start = IH_GPIO_BASE + 32,
- .bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .suspend_support = true,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio3 = {
@@ -156,8 +191,9 @@ static struct __initdata resource omap16xx_gpio4_resources[] = {
static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
.virtual_irq_start = IH_GPIO_BASE + 48,
- .bank_type = METHOD_GPIO_1610,
.bank_width = 16,
+ .suspend_support = true,
+ .regs = &omap16xx_gpio_regs,
};
static struct platform_device omap16xx_gpio4 = {
@@ -193,8 +229,6 @@ static int __init omap16xx_gpio_init(void)
for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++)
platform_device_register(omap16xx_gpio_dev[i]);
- gpio_bank_count = ARRAY_SIZE(omap16xx_gpio_dev);
-
return 0;
}
postcore_initcall(omap16xx_gpio_init);
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index c6ad248..3ca9600 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -39,11 +39,23 @@ static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap7xx_mpuio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP_MPUIO_IO_CNTL / 2,
+ .datain = OMAP_MPUIO_INPUT_LATCH / 2,
+ .dataout = OMAP_MPUIO_OUTPUT / 2,
+ .irqstatus = OMAP_MPUIO_GPIO_INT / 2,
+ .irqenable = OMAP_MPUIO_GPIO_MASKIT / 2,
+ .irqenable_inv = true,
+ .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE / 2,
+};
+
static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
.virtual_irq_start = IH_MPUIO_BASE,
- .bank_type = METHOD_MPUIO,
- .bank_width = 32,
+ .is_mpuio = true,
+ .bank_width = 16,
.bank_stride = 2,
+ .regs = &omap7xx_mpuio_regs,
};
static struct platform_device omap7xx_mpu_gpio = {
@@ -69,10 +81,21 @@ static struct __initdata resource omap7xx_gpio1_resources[] = {
},
};
+static struct omap_gpio_reg_offs omap7xx_gpio_regs = {
+ .revision = USHRT_MAX,
+ .direction = OMAP7XX_GPIO_DIR_CONTROL,
+ .datain = OMAP7XX_GPIO_DATA_INPUT,
+ .dataout = OMAP7XX_GPIO_DATA_OUTPUT,
+ .irqstatus = OMAP7XX_GPIO_INT_STATUS,
+ .irqenable = OMAP7XX_GPIO_INT_MASK,
+ .irqenable_inv = true,
+ .irqctrl = OMAP7XX_GPIO_INT_CONTROL,
+};
+
static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
.virtual_irq_start = IH_GPIO_BASE,
- .bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio1 = {
@@ -100,8 +123,8 @@ static struct __initdata resource omap7xx_gpio2_resources[] = {
static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
.virtual_irq_start = IH_GPIO_BASE + 32,
- .bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio2 = {
@@ -129,8 +152,8 @@ static struct __initdata resource omap7xx_gpio3_resources[] = {
static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
.virtual_irq_start = IH_GPIO_BASE + 64,
- .bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio3 = {
@@ -158,8 +181,8 @@ static struct __initdata resource omap7xx_gpio4_resources[] = {
static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
.virtual_irq_start = IH_GPIO_BASE + 96,
- .bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio4 = {
@@ -187,8 +210,8 @@ static struct __initdata resource omap7xx_gpio5_resources[] = {
static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
.virtual_irq_start = IH_GPIO_BASE + 128,
- .bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio5 = {
@@ -216,8 +239,8 @@ static struct __initdata resource omap7xx_gpio6_resources[] = {
static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
.virtual_irq_start = IH_GPIO_BASE + 160,
- .bank_type = METHOD_GPIO_7XX,
.bank_width = 32,
+ .regs = &omap7xx_gpio_regs,
};
static struct platform_device omap7xx_gpio6 = {
@@ -255,8 +278,6 @@ static int __init omap7xx_gpio_init(void)
for (i = 0; i < ARRAY_SIZE(omap7xx_gpio_dev); i++)
platform_device_register(omap7xx_gpio_dev[i]);
- gpio_bank_count = ARRAY_SIZE(omap7xx_gpio_dev);
-
return 0;
}
postcore_initcall(omap7xx_gpio_init);
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
index c0e1f48..99971bf 100644
--- a/arch/arm/mach-omap1/mailbox.c
+++ b/arch/arm/mach-omap1/mailbox.c
@@ -151,6 +151,9 @@ static int __devinit omap1_mbox_probe(struct platform_device *pdev)
list[0]->irq = platform_get_irq_byname(pdev, "dsp");
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -ENODEV;
+
mbox_base = ioremap(mem->start, resource_size(mem));
if (!mbox_base)
return -ENOMEM;
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/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 13d7b8f..dc4a8fd 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -53,7 +53,6 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <plat/common.h>
-#include <plat/dmtimer.h>
/*
* ---------------------------------------------------------------------------
@@ -184,9 +183,6 @@ bool __init omap_32k_timer_init(void)
{
omap_init_clocksource_32k();
-#ifdef CONFIG_OMAP_DM_TIMER
- omap_dm_timer_init();
-#endif
omap_init_32k_timer();
return true;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 841ae21..3924ddb 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -45,12 +45,13 @@ config ARCH_OMAP4
select CPU_V7
select ARM_GIC
select LOCAL_TIMERS if SMP
- select PL310_ERRATA_588369
- select PL310_ERRATA_727915
+ select PL310_ERRATA_588369 if CONFIG_CACHE_L2X0
+ select PL310_ERRATA_727915 if CONFIG_CACHE_L2X0
select ARM_ERRATA_720789
select ARCH_HAS_OPP
select PM_OPP if PM
select USB_ARCH_HAS_EHCI
+ select ARCH_HAS_BARRIERS
comment "OMAP Core Type"
depends on ARCH_OMAP2
@@ -314,6 +315,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"
@@ -343,6 +345,42 @@ 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
+
+config OMAP_FIQ_DEBUGGER
+ bool "Enable the serial FIQ debugger on OMAP"
+ default y
+ select FIQ_DEBUGGER
+ help
+ Enables the serial FIQ debugger on OMAP"
+
+config OMAP4_PPA_CPU1_ONLINE_BUG
+ bool "Enable Support for CPU1 ONLINE WA for OSWR/OFF"
+ depends on ARCH_OMAP4
+ depends on OMAP_ALLOW_OSWR
+ default y
+ help
+ If an non GP OMAP4 device is used and PPA revision is < v1.7.3,
+ the device does not perform the memory maintenance and TLB sync
+ operations required before releasing CPU1 to HLOS. This results
+ in crash while resuming from OFF mode.
+
+ Disable this option *ONLY IF* you meet the minimum PPA version
+ requirement.
+
+ If, on the other hand, you do not understand the change, leave the
+ default as enabled.
+
endmenu
endif
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b148077..aa42baf 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 dmtimer.o
omap-2-3-common = irq.o sdrc.o
hwmod-common = omap_hwmod.o \
@@ -15,16 +15,20 @@ clock-common = clock.o clock_common_data.o \
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common)
obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP4) += emif.o lpddr2_jedec_data.o lpddr2_elpida_data.o
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
+obj-$(CONFIG_OMAP_TPS6236X) += omap_tps6236x.o
+obj-$(CONFIG_OMAP_TEMP_SENSOR) +=temp_sensor_device.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 +60,29 @@ 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 resetreason.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
+ifeq ($(CONFIG_PM_DEBUG),y)
+obj-$(CONFIG_ARCH_OMAP4) += prcm-debug.o
+endif
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
+obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS1P5) += smartreflex-class1p5.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
@@ -86,16 +100,19 @@ obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
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 omap4-sar.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
+ voltagedomains3xxx_data.o \
+ ldo.o ldo3xxx_data.o dvfs.o
obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \
- voltagedomains44xx_data.o
+ voltagedomains44xx_data.o \
+ ldo.o ldo4xxx_data.o dvfs.o
endif
# OMAP powerdomain framework
@@ -157,13 +174,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)
@@ -241,6 +258,8 @@ obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \
omap_phy_internal.o \
+obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o
+
obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o
obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o \
@@ -270,3 +289,8 @@ 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
+obj-$(CONFIG_OMAP_HSI_DEVICE) += omap_hsi.o
+obj-$(CONFIG_ARCH_OMAP4) += omap_dmm.o
+obj-$(CONFIG_OMAP_FIQ_DEBUGGER) += omap_fiq_debugger.o
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 5dac974..4e2baf7 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -553,106 +553,8 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
-
-static struct omap_device_pad serial1_pads[] __initdata = {
- /*
- * Note that off output enable is an active low
- * signal. So setting this means pin is a
- * input enabled in off mode
- */
- OMAP_MUX_STATIC("uart1_cts.uart1_cts",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart1_rts.uart1_rts",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart1_rx.uart1_rx",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart1_tx.uart1_tx",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial2_pads[] __initdata = {
- OMAP_MUX_STATIC("uart2_cts.uart2_cts",
- OMAP_PIN_INPUT_PULLUP |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rts.uart2_rts",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rx.uart2_rx",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_tx.uart2_tx",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial3_pads[] __initdata = {
- OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
- OMAP_PIN_INPUT_PULLDOWN |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
-};
-
-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 __initdata = {
- .id = 1,
- .pads = serial2_pads,
- .pads_cnt = ARRAY_SIZE(serial2_pads),
-};
-
-static struct omap_board_data serial3_data __initdata = {
- .id = 2,
- .pads = serial3_pads,
- .pads_cnt = ARRAY_SIZE(serial3_pads),
-};
-
-static inline void board_serial_init(void)
-{
- omap_serial_init_port(&serial1_data);
- omap_serial_init_port(&serial2_data);
- omap_serial_init_port(&serial3_data);
-}
#else
#define board_mux NULL
-
-static inline void board_serial_init(void)
-{
- omap_serial_init();
-}
#endif
/*
@@ -789,7 +691,7 @@ static void __init omap_3430sdp_init(void)
else
gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
omap_ads7846_init(1, gpio_pendown, 310, NULL);
- board_serial_init();
+ omap_serial_init();
usb_musb_init(NULL);
board_smc91x_init();
board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 14a5971..8396ac8 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -24,9 +24,14 @@
#include <linux/regulator/machine.h>
#include <linux/leds.h>
#include <linux/leds_pwm.h>
+#include <linux/memblock.h>
#include <mach/hardware.h>
#include <mach/omap4-common.h>
+#include <mach/emif.h>
+#include <mach/lpddr2-elpida.h>
+#include <mach/dmm.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -36,13 +41,16 @@
#include <plat/usb.h>
#include <plat/mmc.h>
#include <plat/omap4-keypad.h>
+#include <plat/remoteproc.h>
#include <video/omapdss.h>
+#include <video/omap-panel-nokia-dsi.h>
#include "mux.h"
#include "hsmmc.h"
#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
@@ -51,6 +59,20 @@
#define OMAP4_SFH7741_ENABLE_GPIO 188
#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define LCD_BL_GPIO 27 /* LCD Backlight GPIO */
+/* PWM2 and TOGGLE3 register offsets */
+#define LED_PWM2ON 0x03
+#define LED_PWM2OFF 0x04
+#define TWL6030_TOGGLE3 0x92
+
+#define TPS62361_GPIO 7
+
+#define PHYS_ADDR_SMC_SIZE (SZ_1M * 3)
+#define PHYS_ADDR_SMC_MEM (0x80000000 + SZ_1G - PHYS_ADDR_SMC_SIZE)
+#define OMAP_ION_HEAP_SECURE_INPUT_SIZE (SZ_1M * 90)
+#define PHYS_ADDR_DUCATI_SIZE (SZ_1M * 105)
+#define PHYS_ADDR_DUCATI_MEM (PHYS_ADDR_SMC_MEM - PHYS_ADDR_DUCATI_SIZE - \
+ OMAP_ION_HEAP_SECURE_INPUT_SIZE)
#define HDMI_GPIO_HPD 63 /* Hotplug detect */
static const int sdp4430_keymap[] = {
@@ -272,24 +294,13 @@ static int __init omap_ethernet_init(void)
return status;
}
-static struct platform_device sdp4430_lcd_device = {
- .name = "sdp4430_lcd",
- .id = -1,
-};
-
static struct platform_device *sdp4430_devices[] __initdata = {
- &sdp4430_lcd_device,
&sdp4430_gpio_keys_device,
&sdp4430_leds_gpio,
&sdp4430_leds_pwm,
};
-static struct omap_lcd_config sdp4430_lcd_config __initdata = {
- .ctrl_name = "internal",
-};
-
static struct omap_board_config_kernel sdp4430_config[] __initdata = {
- { OMAP_TAG_LCD, &sdp4430_lcd_config },
};
static void __init omap_4430sdp_init_early(void)
@@ -345,6 +356,10 @@ static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
.dev_name = "omap_hsmmc.0",
},
};
+static struct regulator_consumer_supply sdp4430_vcxio_supply[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
static int omap4_twl6030_hsmmc_late_init(struct device *dev)
{
@@ -491,7 +506,10 @@ static struct regulator_init_data sdp4430_vcxio = {
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
+ .always_on = true,
},
+ .num_consumer_supplies = ARRAY_SIZE(sdp4430_vcxio_supply),
+ .consumer_supplies = sdp4430_vcxio_supply,
};
static struct regulator_init_data sdp4430_vdac = {
@@ -577,6 +595,76 @@ static void __init omap_sfh7741prox_init(void)
__func__, OMAP4_SFH7741_ENABLE_GPIO, error);
}
+static int dsi1_panel_set_backlight(struct omap_dss_device *dssdev, int level)
+{
+ int r;
+
+ r = twl_i2c_write_u8(TWL_MODULE_PWM, 0x7F, LED_PWM2OFF);
+ if (r)
+ return r;
+
+ if (level > 1) {
+ if (level == 255)
+ level = 0x7F;
+ else
+ level = (~(level/2)) & 0x7F;
+
+ r = twl_i2c_write_u8(TWL_MODULE_PWM, level, LED_PWM2ON);
+ if (r)
+ return r;
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x30, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ } else if (level <= 1) {
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x08, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x28, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x00, TWL6030_TOGGLE3);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static struct nokia_dsi_panel_data dsi1_panel;
+
+static void sdp4430_lcd_init(void)
+{
+ u32 reg;
+ int status;
+
+ /* Enable 3 lanes in DSI1 module, disable pull down */
+ reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+ reg &= ~OMAP4_DSI1_LANEENABLE_MASK;
+ reg |= 0x7 << OMAP4_DSI1_LANEENABLE_SHIFT;
+ reg &= ~OMAP4_DSI1_PIPD_MASK;
+ reg |= 0x7 << OMAP4_DSI1_PIPD_SHIFT;
+ omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+ /* Panel Taal reset and backlight GPIO init */
+ status = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
+ "lcd_reset_gpio");
+ if (status)
+ pr_err("%s: Could not get lcd_reset_gpio\n", __func__);
+
+ if (dsi1_panel.use_ext_te) {
+ status = omap_mux_init_signal("gpmc_ncs4.gpio_101",
+ OMAP_PIN_INPUT_PULLUP);
+ if (status)
+ pr_err("%s: Could not get ext_te gpio\n", __func__);
+ }
+
+ status = gpio_request_one(LCD_BL_GPIO, GPIOF_DIR_OUT, "lcd_bl_gpio");
+ if (status)
+ pr_err("%s: Could not get lcd_bl_gpio\n", __func__);
+
+ gpio_set_value(LCD_BL_GPIO, 0);
+}
+
static void sdp4430_hdmi_mux_init(void)
{
omap_mux_init_signal("hdmi_cec",
@@ -610,6 +698,52 @@ static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
}
+static struct nokia_dsi_panel_data dsi1_panel = {
+ .name = "taal",
+ .reset_gpio = 102,
+ .use_ext_te = false,
+ .ext_te_gpio = 101,
+ .esd_interval = 0,
+ .set_backlight = dsi1_panel_set_backlight,
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+ .name = "lcd",
+ .driver_name = "taal",
+ .type = OMAP_DISPLAY_TYPE_DSI,
+ .data = &dsi1_panel,
+ .phy.dsi = {
+ .clk_lane = 1,
+ .clk_pol = 0,
+ .data1_lane = 2,
+ .data1_pol = 0,
+ .data2_lane = 3,
+ .data2_pol = 0,
+ },
+
+ .clocks = {
+ .dispc = {
+ .channel = {
+ .lck_div = 1, /* Logic Clock = 172.8 MHz */
+ .pck_div = 5, /* Pixel Clock = 34.56 MHz */
+ .lcd_clk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
+ },
+ .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
+ },
+
+ .dsi = {
+ .regn = 16, /* Fint = 2.4 MHz */
+ .regm = 180, /* DDR Clock = 216 MHz */
+ .regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */
+ .regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */
+
+ .lp_clk_div = 10, /* LP Clock = 8.64 MHz */
+ .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
+ },
+ },
+ .channel = OMAP_DSS_CHANNEL_LCD,
+};
+
static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
.hpd_gpio = HDMI_GPIO_HPD,
};
@@ -625,17 +759,19 @@ static struct omap_dss_device sdp4430_hdmi_device = {
};
static struct omap_dss_device *sdp4430_dss_devices[] = {
+ &sdp4430_lcd_device,
&sdp4430_hdmi_device,
};
static struct omap_dss_board_info sdp4430_dss_data = {
.num_devices = ARRAY_SIZE(sdp4430_dss_devices),
.devices = sdp4430_dss_devices,
- .default_device = &sdp4430_hdmi_device,
+ .default_device = &sdp4430_lcd_device,
};
void omap_4430sdp_display_init(void)
{
+ sdp4430_lcd_init();
sdp4430_hdmi_mux_init();
omap_display_init(&sdp4430_dss_data);
@@ -650,67 +786,28 @@ static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
-static struct omap_device_pad serial2_pads[] __initdata = {
- OMAP_MUX_STATIC("uart2_cts.uart2_cts",
- OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rts.uart2_rts",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rx.uart2_rx",
- OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_tx.uart2_tx",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial3_pads[] __initdata = {
- OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
- OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
- OMAP_PIN_INPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial4_pads[] __initdata = {
- OMAP_MUX_STATIC("uart4_rx.uart4_rx",
- OMAP_PIN_INPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart4_tx.uart4_tx",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-};
-
-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 __initdata = {
- .id = 2,
- .pads = serial3_pads,
- .pads_cnt = ARRAY_SIZE(serial3_pads),
-};
-
-static struct omap_board_data serial4_data __initdata = {
- .id = 3,
- .pads = serial4_pads,
- .pads_cnt = ARRAY_SIZE(serial4_pads),
+/*
+ * LPDDR2 Configeration Data:
+ * The memory organisation is as below :
+ * EMIF1 - CS0 - 2 Gb
+ * CS1 - 2 Gb
+ * EMIF2 - CS0 - 2 Gb
+ * CS1 - 2 Gb
+ * --------------------
+ * TOTAL - 8 Gb
+ *
+ * Same devices installed on EMIF1 and EMIF2
+ */
+static __initdata struct emif_device_details emif_devices = {
+ .cs0_device = &lpddr2_elpida_2G_S4_dev,
+ .cs1_device = &lpddr2_elpida_2G_S4_dev
};
-static inline void board_serial_init(void)
+static inline void __init board_serial_init(void)
{
- struct omap_board_data bdata;
- bdata.flags = 0;
- bdata.pads = NULL;
- bdata.pads_cnt = 0;
- bdata.id = 0;
- /* pass dummy data for UART1 */
- omap_serial_init_port(&bdata);
-
- omap_serial_init_port(&serial2_data);
- omap_serial_init_port(&serial3_data);
- omap_serial_init_port(&serial4_data);
+ omap_serial_init();
}
+
#else
#define board_mux NULL
@@ -729,6 +826,8 @@ static void __init omap_4430sdp_init(void)
package = OMAP_PACKAGE_CBL;
omap4_mux_init(board_mux, NULL, package);
+ omap_emif_setup_device_details(&emif_devices, &emif_devices);
+
omap_board_config = sdp4430_config;
omap_board_config_size = ARRAY_SIZE(sdp4430_config);
@@ -753,7 +852,16 @@ static void __init omap_4430sdp_init(void)
if (status)
pr_err("Keypad initialization failed: %d\n", status);
+ omap_dmm_init();
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)
@@ -762,10 +870,22 @@ static void __init omap_4430sdp_map_io(void)
omap44xx_map_common_io();
}
+static void __init omap_4430sdp_reserve(void)
+{
+ /* do the static reservations first */
+ memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE);
+ memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE);
+ /* ipu needs to recognize secure input buffer area as well */
+ omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE +
+ OMAP_ION_HEAP_SECURE_INPUT_SIZE);
+
+ omap_reserve();
+}
+
MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
.boot_params = 0x80000100,
- .reserve = omap_reserve,
+ .reserve = omap_4430sdp_reserve,
.map_io = omap_4430sdp_map_io,
.init_early = omap_4430sdp_init_early,
.init_irq = gic_init_irq,
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 8d74318..5ab626a 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -656,15 +656,15 @@ static inline void board_serial_init(void)
bdata.pads_cnt = 0;
bdata.id = 0;
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
bdata.id = 1;
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
bdata.id = 2;
bdata.pads = serial2_pads;
bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
}
#else
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 107dfc3..5f42052 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -28,9 +28,14 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/wl12xx.h>
+#include <linux/memblock.h>
#include <mach/hardware.h>
#include <mach/omap4-common.h>
+#include <mach/emif.h>
+#include <mach/lpddr2-elpida.h>
+#include <mach/dmm.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -40,6 +45,7 @@
#include <plat/common.h>
#include <plat/usb.h>
#include <plat/mmc.h>
+#include <plat/remoteproc.h>
#include <video/omap-panel-generic-dpi.h>
#include "timer-gp.h"
@@ -56,6 +62,14 @@
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
#define HDMI_GPIO_HPD 63 /* Hotplug detect */
+
+#define PHYS_ADDR_SMC_SIZE (SZ_1M * 3)
+#define PHYS_ADDR_SMC_MEM (0x80000000 + SZ_1G - PHYS_ADDR_SMC_SIZE)
+#define OMAP_ION_HEAP_SECURE_INPUT_SIZE (SZ_1M * 90)
+#define PHYS_ADDR_DUCATI_SIZE (SZ_1M * 105)
+#define PHYS_ADDR_DUCATI_MEM (PHYS_ADDR_SMC_MEM - PHYS_ADDR_DUCATI_SIZE - \
+ OMAP_ION_HEAP_SECURE_INPUT_SIZE)
+
/* wl127x BT, FM, GPS connectivity chip */
static int wl1271_gpios[] = {46, -1, -1};
static struct platform_device wl1271_device = {
@@ -152,7 +166,11 @@ static void __init omap4_ehci_init(void)
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_UTMI,
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+ .mode = MUSB_PERIPHERAL,
+#else
.mode = MUSB_OTG,
+#endif
.power = 100,
};
@@ -381,6 +399,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,
@@ -396,6 +432,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,
};
/*
@@ -498,71 +537,14 @@ static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
-static struct omap_device_pad serial2_pads[] __initdata = {
- OMAP_MUX_STATIC("uart2_cts.uart2_cts",
- OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rts.uart2_rts",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rx.uart2_rx",
- OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_tx.uart2_tx",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial3_pads[] __initdata = {
- OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
- OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
- OMAP_PIN_INPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial4_pads[] __initdata = {
- OMAP_MUX_STATIC("uart4_rx.uart4_rx",
- OMAP_PIN_INPUT | OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart4_tx.uart4_tx",
- OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-};
-
-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 __initdata = {
- .id = 2,
- .pads = serial3_pads,
- .pads_cnt = ARRAY_SIZE(serial3_pads),
-};
-
-static struct omap_board_data serial4_data __initdata = {
- .id = 3,
- .pads = serial4_pads,
- .pads_cnt = ARRAY_SIZE(serial4_pads),
-};
-
-static inline void board_serial_init(void)
+static inline void __init board_serial_init(void)
{
- struct omap_board_data bdata;
- bdata.flags = 0;
- bdata.pads = NULL;
- bdata.pads_cnt = 0;
- bdata.id = 0;
- /* pass dummy data for UART1 */
- omap_serial_init_port(&bdata);
-
- omap_serial_init_port(&serial2_data);
- omap_serial_init_port(&serial3_data);
- omap_serial_init_port(&serial4_data);
+ omap_serial_init();
}
#else
#define board_mux NULL
-static inline void board_serial_init(void)
+static inline void __init board_serial_init(void)
{
omap_serial_init();
}
@@ -584,7 +566,7 @@ static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
/* Using generic display panel */
static struct panel_generic_dpi_data omap4_dvi_panel = {
- .name = "generic",
+ .name = "generic_720p",
.platform_enable = omap4_panda_enable_dvi,
.platform_disable = omap4_panda_disable_dvi,
};
@@ -671,6 +653,23 @@ static struct omap_dss_board_info omap4_panda_dss_data = {
.default_device = &omap4_panda_dvi_device,
};
+/*
+ * LPDDR2 Configeration Data:
+ * The memory organisation is as below :
+ * EMIF1 - CS0 - 2 Gb
+ * CS1 - 2 Gb
+ * EMIF2 - CS0 - 2 Gb
+ * CS1 - 2 Gb
+ * --------------------
+ * TOTAL - 8 Gb
+ *
+ * Same devices installed on EMIF1 and EMIF2
+ */
+static __initdata struct emif_device_details emif_devices = {
+ .cs0_device = &lpddr2_elpida_2G_S4_dev,
+ .cs1_device = &lpddr2_elpida_2G_S4_dev
+};
+
void omap4_panda_display_init(void)
{
int r;
@@ -687,10 +686,14 @@ void omap4_panda_display_init(void)
omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
}
+extern void __init omap4_panda_android_init(void);
+
static void __init omap4_panda_init(void)
{
int package = OMAP_PACKAGE_CBS;
+ omap_emif_setup_device_details(&emif_devices, &emif_devices);
+
if (omap_rev() == OMAP4430_REV_ES1_0)
package = OMAP_PACKAGE_CBL;
omap4_mux_init(board_mux, NULL, package);
@@ -699,13 +702,23 @@ static void __init omap4_panda_init(void)
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();
usb_musb_init(&musb_board_data);
+
+ omap_dmm_init();
omap4_panda_display_init();
+
}
static void __init omap4_panda_map_io(void)
@@ -714,10 +727,22 @@ static void __init omap4_panda_map_io(void)
omap44xx_map_common_io();
}
+static void __init omap4_panda_reserve(void)
+{
+ /* do the static reservations first */
+ memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE);
+ memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE);
+ /* ipu needs to recognize secure input buffer area as well */
+ omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE +
+ OMAP_ION_HEAP_SECURE_INPUT_SIZE);
+
+ omap_reserve();
+}
+
MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
/* Maintainer: David Anders - Texas Instruments Inc */
.boot_params = 0x80000100,
- .reserve = omap_reserve,
+ .reserve = omap4_panda_reserve,
.map_io = omap4_panda_map_io,
.init_early = omap4_panda_init_early,
.init_irq = gic_init_irq,
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..450aabf 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -41,6 +41,7 @@
/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
#define DPLL_LOW_POWER_STOP 0x1
+#define DPLL_MN_BYPASS 0x4
#define DPLL_LOW_POWER_BYPASS 0x5
#define DPLL_LOCKED 0x7
@@ -64,6 +65,11 @@ 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);
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
#ifdef CONFIG_OMAP_RESET_CLOCKS
void omap2_clk_disable_unused(struct clk *clk);
@@ -132,6 +138,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 +148,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 +158,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/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 2926d02..f44d070 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1820,29 +1820,29 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X),
/* general l4 interface ck, multi-parent functional clk */
CLK(NULL, "gpt1_ick", &gpt1_ick, CK_242X),
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_242X),
+ CLK("omap_timer.1", "fck", &gpt1_fck, CK_242X),
CLK(NULL, "gpt2_ick", &gpt2_ick, CK_242X),
- CLK(NULL, "gpt2_fck", &gpt2_fck, CK_242X),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_242X),
CLK(NULL, "gpt3_ick", &gpt3_ick, CK_242X),
- CLK(NULL, "gpt3_fck", &gpt3_fck, CK_242X),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_242X),
CLK(NULL, "gpt4_ick", &gpt4_ick, CK_242X),
- CLK(NULL, "gpt4_fck", &gpt4_fck, CK_242X),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_242X),
CLK(NULL, "gpt5_ick", &gpt5_ick, CK_242X),
- CLK(NULL, "gpt5_fck", &gpt5_fck, CK_242X),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_242X),
CLK(NULL, "gpt6_ick", &gpt6_ick, CK_242X),
- CLK(NULL, "gpt6_fck", &gpt6_fck, CK_242X),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_242X),
CLK(NULL, "gpt7_ick", &gpt7_ick, CK_242X),
- CLK(NULL, "gpt7_fck", &gpt7_fck, CK_242X),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_242X),
CLK(NULL, "gpt8_ick", &gpt8_ick, CK_242X),
- CLK(NULL, "gpt8_fck", &gpt8_fck, CK_242X),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_242X),
CLK(NULL, "gpt9_ick", &gpt9_ick, CK_242X),
- CLK(NULL, "gpt9_fck", &gpt9_fck, CK_242X),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_242X),
CLK(NULL, "gpt10_ick", &gpt10_ick, CK_242X),
- CLK(NULL, "gpt10_fck", &gpt10_fck, CK_242X),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_242X),
CLK(NULL, "gpt11_ick", &gpt11_ick, CK_242X),
- CLK(NULL, "gpt11_fck", &gpt11_fck, CK_242X),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_242X),
CLK(NULL, "gpt12_ick", &gpt12_ick, CK_242X),
- CLK(NULL, "gpt12_fck", &gpt12_fck, CK_242X),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_242X),
CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_242X),
CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_242X),
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_242X),
@@ -1898,6 +1898,54 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "pka_ick", &pka_ick, CK_242X),
CLK(NULL, "usb_fck", &usb_fck, CK_242X),
CLK("musb-hdrc", "fck", &osc_ck, CK_242X),
+ CLK("omap_timer.1", "fck", &gpt1_fck, CK_242X),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_242X),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_242X),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_242X),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_242X),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_242X),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_242X),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_242X),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_242X),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_242X),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_242X),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_242X),
+ CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X),
};
/*
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 0c79d39..cffd1c3 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1910,29 +1910,29 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X),
/* general l4 interface ck, multi-parent functional clk */
CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X),
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X),
+ CLK("omap_timer.1", "fck", &gpt1_fck, CK_243X),
CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X),
- CLK(NULL, "gpt2_fck", &gpt2_fck, CK_243X),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_243X),
CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X),
- CLK(NULL, "gpt3_fck", &gpt3_fck, CK_243X),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_243X),
CLK(NULL, "gpt4_ick", &gpt4_ick, CK_243X),
- CLK(NULL, "gpt4_fck", &gpt4_fck, CK_243X),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_243X),
CLK(NULL, "gpt5_ick", &gpt5_ick, CK_243X),
- CLK(NULL, "gpt5_fck", &gpt5_fck, CK_243X),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_243X),
CLK(NULL, "gpt6_ick", &gpt6_ick, CK_243X),
- CLK(NULL, "gpt6_fck", &gpt6_fck, CK_243X),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_243X),
CLK(NULL, "gpt7_ick", &gpt7_ick, CK_243X),
- CLK(NULL, "gpt7_fck", &gpt7_fck, CK_243X),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_243X),
CLK(NULL, "gpt8_ick", &gpt8_ick, CK_243X),
- CLK(NULL, "gpt8_fck", &gpt8_fck, CK_243X),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_243X),
CLK(NULL, "gpt9_ick", &gpt9_ick, CK_243X),
- CLK(NULL, "gpt9_fck", &gpt9_fck, CK_243X),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_243X),
CLK(NULL, "gpt10_ick", &gpt10_ick, CK_243X),
- CLK(NULL, "gpt10_fck", &gpt10_fck, CK_243X),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_243X),
CLK(NULL, "gpt11_ick", &gpt11_ick, CK_243X),
- CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_243X),
CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X),
- CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_243X),
CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X),
CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_243X),
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X),
@@ -1998,6 +1998,42 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X),
CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X),
CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X),
+ CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X),
};
/*
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/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 75b119b..a7d698a 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3280,12 +3280,12 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "modem_fck", &modem_fck, CK_34XX | CK_36XX),
CLK(NULL, "sad2d_ick", &sad2d_ick, CK_34XX | CK_36XX),
CLK(NULL, "mad2d_ick", &mad2d_ick, CK_34XX | CK_36XX),
- CLK(NULL, "gpt10_fck", &gpt10_fck, CK_3XXX),
- CLK(NULL, "gpt11_fck", &gpt11_fck, CK_3XXX),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_3XXX),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_3XXX),
CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX),
CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX),
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
@@ -3321,7 +3321,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX),
CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
@@ -3367,22 +3367,22 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX),
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
+ CLK("omap_timer.1", "fck", &gpt1_fck, CK_3XXX),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_3XXX),
CLK("omap_wdt", "fck", &wdt2_fck, CK_3XXX),
@@ -3401,14 +3401,14 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX),
CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX),
CLK(NULL, "uart4_fck", &uart4_fck, CK_36XX),
- CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX),
- CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX),
- CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX),
- CLK(NULL, "gpt5_fck", &gpt5_fck, CK_3XXX),
- CLK(NULL, "gpt6_fck", &gpt6_fck, CK_3XXX),
- CLK(NULL, "gpt7_fck", &gpt7_fck, CK_3XXX),
- CLK(NULL, "gpt8_fck", &gpt8_fck, CK_3XXX),
- CLK(NULL, "gpt9_fck", &gpt9_fck, CK_3XXX),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_3XXX),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_3XXX),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_3XXX),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_3XXX),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_3XXX),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_3XXX),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_3XXX),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_3XXX),
CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_3XXX),
CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_3XXX),
@@ -3449,7 +3449,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "sr2_fck", &sr2_fck, CK_34XX | CK_36XX),
CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_34XX | CK_36XX),
CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_3XXX),
- CLK(NULL, "gpt12_fck", &gpt12_fck, CK_3XXX),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_3XXX),
CLK(NULL, "wdt1_fck", &wdt1_fck, CK_3XXX),
CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX),
CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX),
@@ -3462,6 +3462,30 @@ static struct omap_clk omap3xxx_clks[] = {
CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX),
CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX),
CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX),
+ CLK("omap_timer.1", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.2", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.3", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.4", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.5", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.6", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.7", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.8", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.9", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.10", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.11", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.12", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.1", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.2", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.3", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.4", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.5", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.6", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.7", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.8", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.9", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.10", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.11", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.12", "sys_ck", &sys_ck, CK_3XXX),
};
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
index 6be1095..bdc5f0d 100644
--- a/arch/arm/mach-omap2/clock44xx.h
+++ b/arch/arm/mach-omap2/clock44xx.h
@@ -14,7 +14,9 @@
*/
#define OMAP4430_MAX_DPLL_MULT 2047
#define OMAP4430_MAX_DPLL_DIV 128
+#define OMAP4430_REGM4XEN_MULT 4
int omap4xxx_clk_init(void);
+int omap4_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
#endif
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 8c96567..6089ff0 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 },
};
@@ -194,12 +198,6 @@ static struct clk tie_low_clock_ck = {
.ops = &clkops_null,
};
-static struct clk utmi_phy_clkout_ck = {
- .name = "utmi_phy_clkout_ck",
- .rate = 60000000,
- .ops = &clkops_null,
-};
-
static struct clk xclk60mhsp1_ck = {
.name = "xclk60mhsp1_ck",
.rate = 60000000,
@@ -270,8 +268,8 @@ static struct clk dpll_abe_ck = {
.dpll_data = &dpll_abe_dd,
.init = &omap2_init_dpll_parent,
.ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
+ .recalc = &omap4_dpll_regm4xen_recalc,
+ .round_rate = &omap4_dpll_regm4xen_round_rate,
.set_rate = &omap3_noncore_dpll_set_rate,
};
@@ -285,37 +283,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 +343,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 +367,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 },
};
@@ -501,7 +499,7 @@ static struct clk dpll_core_m2_ck = {
.ops = &clkops_omap4_dpllmx_ops,
.recalc = &omap2_clksel_recalc,
.round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
+ .set_rate = &omap4_core_dpll_m2_set_rate,
};
static struct clk ddrphy_ck = {
@@ -524,6 +522,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 +549,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 +628,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 +781,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 +895,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,
@@ -1007,7 +1023,8 @@ static struct dpll_data dpll_usb_dd = {
.flags = DPLL_J_TYPE,
.clk_ref = &sys_clkin_ck,
.control_reg = OMAP4430_CM_CLKMODE_DPLL_USB,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED)
+ | (1 << DPLL_LOW_POWER_STOP),
.autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB,
.idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB,
.mult_mask = OMAP4430_DPLL_MULT_MASK,
@@ -1030,6 +1047,7 @@ static struct clk dpll_usb_ck = {
.recalc = &omap3_dpll_recalc,
.round_rate = &omap2_dpll_round_rate,
.set_rate = &omap3_noncore_dpll_set_rate,
+ .clkdm_name = "l3_init_clkdm",
};
static struct clk dpll_usb_clkdcoldo_ck = {
@@ -1040,6 +1058,13 @@ static struct clk dpll_usb_clkdcoldo_ck = {
.recalc = &followparent_recalc,
};
+static struct clk utmi_phy_clkout_ck = {
+ .name = "utmi_phy_clkout_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_usb_clkdcoldo_ck,
+ .recalc = &followparent_recalc,
+};
+
static const struct clksel dpll_usb_m2_div[] = {
{ .parent = &dpll_usb_ck, .rates = div31_1to31_rates },
{ .parent = NULL },
@@ -1099,8 +1124,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 +1155,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 +1208,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 +1289,28 @@ static struct clk l4_wkup_clk_mux_ck = {
.recalc = &omap2_clksel_recalc,
};
+static const struct clksel_rate div3_8to32_rates[] = {
+ { .div = 8, .val = 0, .flags = RATE_IN_44XX },
+ { .div = 16, .val = 1, .flags = RATE_IN_44XX },
+ { .div = 32, .val = 2, .flags = RATE_IN_44XX },
+ { .div = 0 },
+};
+
+static const struct clksel div_ts_ck_div[] = {
+ { .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
+ { .parent = NULL },
+};
+
+static struct clk div_ts_ck = {
+ .name = "div_ts_ck",
+ .parent = &l4_wkup_clk_mux_ck,
+ .clksel = div_ts_ck_div,
+ .clksel_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_24_25_MASK,
+ .ops = &clkops_null,
+ .recalc = &omap2_clksel_recalc,
+};
+
static const struct clksel per_abe_nc_fclk_div[] = {
{ .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates },
{ .parent = NULL },
@@ -1358,7 +1405,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 +1415,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 +1425,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 +1435,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 +1443,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 +1496,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 +1505,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,17 +1515,20 @@ 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",
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = ENABLE_ON_INIT,
+#endif
.parent = &syc_clk_div_ck,
.recalc = &followparent_recalc,
};
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 +1538,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 +1548,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,17 +1558,20 @@ 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",
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = ENABLE_ON_INIT,
+#endif
.parent = &l3_div_ck,
.recalc = &followparent_recalc,
};
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,10 +1581,9 @@ 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,
.clkdm_name = "l3_emif_clkdm",
.parent = &ddrphy_ck,
.recalc = &followparent_recalc,
@@ -1529,10 +1591,9 @@ 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,
.clkdm_name = "l3_emif_clkdm",
.parent = &ddrphy_ck,
.recalc = &followparent_recalc,
@@ -1550,7 +1611,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 +1622,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 +1632,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 +1642,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 +1652,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 +1662,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 +1672,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 +1682,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 +1692,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 +1702,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 +1712,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 +1722,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 +1732,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 +1742,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,10 +1752,11 @@ 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",
+ .flags = ENABLE_ON_INIT,
.parent = &l3_div_ck,
.recalc = &followparent_recalc,
};
@@ -1713,7 +1775,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 +1784,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 +1804,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 +1815,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 +1825,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 +1835,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 +1845,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 +1855,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 +1865,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 +1875,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 +1885,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 +1895,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 +1905,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 +1916,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 +1951,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 +1984,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 +2017,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 +2050,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 +2082,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 +2091,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 +2101,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 +2111,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 +2121,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 +2131,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 +2147,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 +2162,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 +2171,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 +2181,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 +2191,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 +2201,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 +2211,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 +2221,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 +2232,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 +2242,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 +2252,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 +2262,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 +2272,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 +2282,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 +2292,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 +2302,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 +2312,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 +2322,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 +2332,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 +2342,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 +2352,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 +2362,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 +2372,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 +2388,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 +2403,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 +2418,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 +2433,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 +2448,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 +2463,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 +2484,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 +2499,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 +2514,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 +2529,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 +2544,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 +2553,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 +2563,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 +2573,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 +2583,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 +2593,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 +2620,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 +2647,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 +2657,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 +2667,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 +2677,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 +2687,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 +2697,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 +2707,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 +2717,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 +2744,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,17 +2754,17 @@ 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",
- .parent = &l3_div_ck,
+ .parent = &otg_60m_gfclk,
.recalc = &followparent_recalc,
};
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 +2774,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 +2784,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 +2794,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 +2804,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 +2813,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 +2837,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 +2847,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 +2857,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 +2867,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 +2912,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 +2952,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 +2982,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 +3042,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 +3072,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 +3102,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 +3195,448 @@ static struct clk auxclkreq5_ck = {
.recalc = &omap2_clksel_recalc,
};
+static struct clk smp_twd_443x = {
+ .name = "smp_twd",
+ .parent = &dpll_mpu_ck,
+ .ops = &clkops_null,
+ .fixed_div = 2,
+ .recalc = &omap_fixed_divisor_recalc,
+};
+
+static struct clk smp_twd_446x = {
+ .name = "smp_twd",
+ .parent = &virt_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, "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("omapdss_dss", "sys_clk", &dss_sys_clk, CK_443X),
- CLK("omapdss_dss", "tv_clk", &dss_tv_clk, CK_443X),
- CLK("omapdss_dss", "video_clk", &dss_48mhz_clk, CK_443X),
- CLK("omapdss_dss", "fck", &dss_dss_clk, CK_443X),
- CLK("omapdss_dss", "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, "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("omap_temp_sensor.0", "fck", &bandgap_fclk, CK_443X),
+ CLK("omap_temp_sensor.0", "fck", &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("omap_timer.1", "fck", &timer1_fck, CK_44XX),
+ CLK("omap_timer.10", "fck", &timer10_fck, CK_44XX),
+ CLK("omap_timer.11", "fck", &timer11_fck, CK_44XX),
+ CLK("omap_timer.2", "fck", &timer2_fck, CK_44XX),
+ CLK("omap_timer.3", "fck", &timer3_fck, CK_44XX),
+ CLK("omap_timer.4", "fck", &timer4_fck, CK_44XX),
+ CLK("omap_timer.5", "fck", &timer5_fck, CK_44XX),
+ CLK("omap_timer.6", "fck", &timer6_fck, CK_44XX),
+ CLK("omap_timer.7", "fck", &timer7_fck, CK_44XX),
+ CLK("omap_timer.8", "fck", &timer8_fck, CK_44XX),
+ CLK("omap_timer.9", "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", "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", "hs_fck", &usb_host_hs_fck, CK_44XX),
+ CLK("usbhs_omap", "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", "usbtll_ick", &usb_tll_hs_ick, CK_44XX),
+ CLK("usbhs_omap", "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("smp_twd", NULL, &smp_twd_443x, CK_443X),
+ CLK("smp_twd", NULL, &smp_twd_446x, CK_446X),
+ CLK("omap_timer.1", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.2", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.3", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.4", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.5", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.6", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.7", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.8", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.9", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.10", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.11", "32k_ck", &sys_32k_ck, CK_44XX),
+ CLK("omap_timer.1", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.2", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.3", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.4", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.9", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.10", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.11", "sys_ck", &sys_clkin_ck, CK_44XX),
+ CLK("omap_timer.5", "sys_ck", &syc_clk_div_ck, CK_44XX),
+ CLK("omap_timer.6", "sys_ck", &syc_clk_div_ck, CK_44XX),
+ CLK("omap_timer.7", "sys_ck", &syc_clk_div_ck, CK_44XX),
+ CLK("omap_timer.8", "sys_ck", &syc_clk_div_ck, CK_44XX),
+};
+
+#define L3_OPP50_RATE 100000000
+#define DPLL_CORE_M2_OPP50_RATE 400000000
+#define DPLL_CORE_M2_OPP100_RATE 800000000
+#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->parent, 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_m2_rate;
+ 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_m2_rate = DPLL_CORE_M2_OPP50_RATE,
+ .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_m2_rate = DPLL_CORE_M2_OPP100_RATE,
+ .core_m3_rate = DPLL_CORE_M3_OPP100_RATE,
+ .core_m6_rate = DPLL_CORE_M6_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);
+ omap4_clksel_set_rate(&dpll_core_m2_ck, l3_deps->core_m2_rate);
+
+ 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..583cc3d 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -718,6 +718,8 @@ int clkdm_sleep(struct clockdomain *clkdm)
*/
int clkdm_wakeup(struct clockdomain *clkdm)
{
+ int ret;
+
if (!clkdm)
return -EINVAL;
@@ -732,7 +734,10 @@ int clkdm_wakeup(struct clockdomain *clkdm)
pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
- return arch_clkdm->clkdm_wakeup(clkdm);
+ ret = arch_clkdm->clkdm_wakeup(clkdm);
+ ret |= pwrdm_wait_transition(clkdm->pwrdm.ptr);
+
+ return ret;
}
/**
@@ -795,6 +800,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 +851,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..8c73442 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 = {
@@ -411,7 +411,7 @@ static struct clockdomain tesla_44xx_clkdm = {
.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),
+ .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 = {
@@ -560,7 +560,7 @@ static struct clockdomain ducati_44xx_clkdm = {
.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),
+ .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/cm1_44xx.h b/arch/arm/mach-omap2/cm1_44xx.h
index e2d7a56..6a34bed 100644
--- a/arch/arm/mach-omap2/cm1_44xx.h
+++ b/arch/arm/mach-omap2/cm1_44xx.h
@@ -82,8 +82,8 @@
#define OMAP4430_CM_DIV_M7_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0044)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET 0x0048
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0048)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_OFFSET 0x004c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_OFFSET 0x004c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
#define OMAP4_CM_EMU_OVERRIDE_DPLL_CORE_OFFSET 0x0050
#define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0050)
#define OMAP4_CM_CLKMODE_DPLL_MPU_OFFSET 0x0060
@@ -98,8 +98,8 @@
#define OMAP4430_CM_DIV_M2_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0070)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET 0x0088
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0088)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_MPU_OFFSET 0x008c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_MPU_OFFSET 0x008c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
#define OMAP4_CM_BYPCLK_DPLL_MPU_OFFSET 0x009c
#define OMAP4430_CM_BYPCLK_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x009c)
#define OMAP4_CM_CLKMODE_DPLL_IVA_OFFSET 0x00a0
@@ -116,8 +116,8 @@
#define OMAP4430_CM_DIV_M5_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00bc)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_IVA_OFFSET 0x00c8
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00c8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_IVA_OFFSET 0x00cc
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_IVA_OFFSET 0x00cc
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
#define OMAP4_CM_BYPCLK_DPLL_IVA_OFFSET 0x00dc
#define OMAP4430_CM_BYPCLK_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00dc)
#define OMAP4_CM_CLKMODE_DPLL_ABE_OFFSET 0x00e0
@@ -134,8 +134,8 @@
#define OMAP4430_CM_DIV_M3_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00f4)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_ABE_OFFSET 0x0108
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0108)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_ABE_OFFSET 0x010c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_ABE_OFFSET 0x010c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
#define OMAP4_CM_CLKMODE_DPLL_DDRPHY_OFFSET 0x0120
#define OMAP4430_CM_CLKMODE_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0120)
#define OMAP4_CM_IDLEST_DPLL_DDRPHY_OFFSET 0x0124
@@ -154,8 +154,8 @@
#define OMAP4430_CM_DIV_M6_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0140)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_DDRPHY_OFFSET 0x0148
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0148)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_DDRPHY_OFFSET 0x014c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_DDRPHY_OFFSET 0x014c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
#define OMAP4_CM_SHADOW_FREQ_CONFIG1_OFFSET 0x0160
#define OMAP4430_CM_SHADOW_FREQ_CONFIG1 OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0160)
#define OMAP4_CM_SHADOW_FREQ_CONFIG2_OFFSET 0x0164
@@ -236,8 +236,8 @@
#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x001c)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET 0x0020
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0020)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE_OFFSET 0x0024
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0024)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET 0x0024
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0024)
#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET 0x0028
#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0028)
#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET 0x002c
@@ -253,9 +253,11 @@
#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET 0x0040
#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0040)
+#ifndef __ASSEMBLER__
/* Function prototypes */
extern u32 omap4_cm1_read_inst_reg(s16 inst, u16 idx);
extern void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 idx);
extern u32 omap4_cm1_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+#endif
#endif
diff --git a/arch/arm/mach-omap2/cm2_44xx.h b/arch/arm/mach-omap2/cm2_44xx.h
index aa47450..b6ed984 100644
--- a/arch/arm/mach-omap2/cm2_44xx.h
+++ b/arch/arm/mach-omap2/cm2_44xx.h
@@ -121,8 +121,8 @@
#define OMAP4430_CM_DIV_M7_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0064)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET 0x0068
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0068)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_PER_OFFSET 0x006c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET 0x006c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
#define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET 0x0080
#define OMAP4430_CM_CLKMODE_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0080)
#define OMAP4_CM_IDLEST_DPLL_USB_OFFSET 0x0084
@@ -135,8 +135,8 @@
#define OMAP4430_CM_DIV_M2_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0090)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_USB_OFFSET 0x00a8
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00a8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_USB_OFFSET 0x00ac
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_USB_OFFSET 0x00ac
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
#define OMAP4_CM_CLKDCOLDO_DPLL_USB_OFFSET 0x00b4
#define OMAP4430_CM_CLKDCOLDO_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00b4)
#define OMAP4_CM_CLKMODE_DPLL_UNIPRO_OFFSET 0x00c0
@@ -151,8 +151,8 @@
#define OMAP4430_CM_DIV_M2_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00d0)
#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_UNIPRO_OFFSET 0x00e8
#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00e8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_UNIPRO_OFFSET 0x00ec
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_UNIPRO_OFFSET 0x00ec
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
/* CM2.ALWAYS_ON_CM2 register offsets */
#define OMAP4_CM_ALWON_CLKSTCTRL_OFFSET 0x0000
@@ -500,9 +500,11 @@
#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET 0x005c
#define OMAP4430_CM_SDMA_STATICDEP_RESTORE OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x005c)
+#ifndef __ASSEMBLER__
/* Function prototypes */
extern u32 omap4_cm2_read_inst_reg(s16 inst, u16 idx);
extern void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 idx);
extern u32 omap4_cm2_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+#endif
#endif
diff --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c
index e96f53e..16d5f3d 100644
--- a/arch/arm/mach-omap2/cm44xx.c
+++ b/arch/arm/mach-omap2/cm44xx.c
@@ -21,8 +21,11 @@
#include <plat/common.h>
#include "cm.h"
+#include "cm44xx.h"
#include "cm1_44xx.h"
#include "cm2_44xx.h"
+#include "cminst44xx.h"
+#include "prcm44xx.h"
#include "cm-regbits-44xx.h"
/* CM1 hardware module low-level functions */
@@ -50,3 +53,322 @@ void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 reg)
{
__raw_writel(val, OMAP44XX_CM2_REGADDR(inst, reg));
}
+
+#define MAX_CM_REGISTERS 51
+
+struct omap4_cm_tuple {
+ u16 addr;
+ u32 val;
+};
+
+struct omap4_cm_regs {
+ u32 mod_off;
+ u32 no_reg;
+ struct omap4_cm_tuple reg[MAX_CM_REGISTERS];
+};
+
+static struct omap4_cm_regs cm1_regs[] = {
+ /* OMAP4430_CM1_OCP_SOCKET_MOD */
+ { .mod_off = OMAP4430_CM1_OCP_SOCKET_INST, .no_reg = 1,
+ {{.addr = OMAP4_CM_CM1_PROFILING_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM1_CKGEN_MOD */
+ { .mod_off = OMAP4430_CM1_CKGEN_INST, .no_reg = 4,
+ {{.addr = OMAP4_CM_CLKSEL_CORE_OFFSET},
+ {.addr = OMAP4_CM_CLKSEL_ABE_OFFSET},
+ {.addr = OMAP4_CM_DLL_CTRL_OFFSET},
+ {.addr = OMAP4_CM_DYN_DEP_PRESCAL_OFFSET} },
+ },
+ /* OMAP4430_CM1_MPU_MOD */
+ { .mod_off = OMAP4430_CM1_MPU_INST, .no_reg = 4,
+ {{.addr = OMAP4_CM_MPU_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_MPU_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_MPU_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM1_TESLA_MOD */
+ { .mod_off = OMAP4430_CM1_TESLA_INST, .no_reg = 4,
+ {{.addr = OMAP4_CM_TESLA_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_TESLA_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_TESLA_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM1_ABE_MOD */
+ { .mod_off = OMAP4430_CM1_ABE_INST, .no_reg = 15,
+ {{.addr = OMAP4_CM1_ABE_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_SLIMBUS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET} },
+ },
+};
+
+static struct omap4_cm_regs cm2_regs[] = {
+ /* OMAP4430_CM2_OCP_SOCKET_MOD */
+ {.mod_off = OMAP4430_CM2_OCP_SOCKET_INST, .no_reg = 1,
+ {{.addr = OMAP4_CM_CM2_PROFILING_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_CKGEN_MOD */
+ {.mod_off = OMAP4430_CM2_CKGEN_INST, .no_reg = 12,
+ {{.addr = OMAP4_CM_CLKSEL_DUCATI_ISS_ROOT_OFFSET},
+ {.addr = OMAP4_CM_CLKSEL_USB_60MHZ_OFFSET},
+ {.addr = OMAP4_CM_SCALE_FCLK_OFFSET},
+ {.addr = OMAP4_CM_CORE_DVFS_PERF1_OFFSET},
+ {.addr = OMAP4_CM_CORE_DVFS_PERF2_OFFSET},
+ {.addr = OMAP4_CM_CORE_DVFS_PERF3_OFFSET},
+ {.addr = OMAP4_CM_CORE_DVFS_PERF4_OFFSET},
+ {.addr = OMAP4_CM_CORE_DVFS_CURRENT_OFFSET},
+ {.addr = OMAP4_CM_IVA_DVFS_PERF_TESLA_OFFSET},
+ {.addr = OMAP4_CM_IVA_DVFS_PERF_IVAHD_OFFSET},
+ {.addr = OMAP4_CM_IVA_DVFS_PERF_ABE_OFFSET},
+ {.addr = OMAP4_CM_IVA_DVFS_CURRENT_OFFSET} },
+ },
+ /* OMAP4430_CM2_ALWAYS_ON_MOD */
+ {.mod_off = OMAP4430_CM2_ALWAYS_ON_INST, .no_reg = 6,
+ {{.addr = OMAP4_CM_ALWON_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_ALWON_MDMINTC_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_CORE_MOD */
+ {.mod_off = OMAP4430_CM2_CORE_INST, .no_reg = 41,
+ {{.addr = OMAP4_CM_L3_1_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3_1_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3_2_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3_2_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3_2_OCMC_RAM_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_DUCATI_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_DUCATI_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_DUCATI_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_SDMA_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_SDMA_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_SDMA_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_EMIF_2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_DLL_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_EMIF_H1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_EMIF_H2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_MEMIF_DLL_H_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_D2D_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_D2D_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_D2D_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_D2D_INSTEM_ICR_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4CFG_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4CFG_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4CFG_SAR_ROM_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INSTR_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_IVAHD_MOD */
+ {.mod_off = OMAP4430_CM2_IVAHD_INST, .no_reg = 5,
+ {{.addr = OMAP4_CM_IVAHD_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_IVAHD_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_IVAHD_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_IVAHD_SL2_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_CAM_MOD */
+ {.mod_off = OMAP4430_CM2_CAM_INST, .no_reg = 5,
+ {{.addr = OMAP4_CM_CAM_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_CAM_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_CAM_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_CAM_FDIF_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_DSS_MOD */
+ {.mod_off = OMAP4430_CM2_DSS_INST, .no_reg = 5,
+ {{.addr = OMAP4_CM_DSS_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_DSS_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_DSS_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_DSS_DEISS_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_GFX_MOD */
+ {.mod_off = OMAP4430_CM2_GFX_INST, .no_reg = 4,
+ {{.addr = OMAP4_CM_GFX_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_GFX_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_GFX_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_L3INIT_MOD */
+ {.mod_off = OMAP4430_CM2_L3INIT_INST, .no_reg = 20,
+ {{.addr = OMAP4_CM_L3INIT_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_UNIPRO1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_P1500_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_EMAC_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_SATA_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_TPPSS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_PCIESS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_CCPTX_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_XHPI_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_MMC6_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_USB_HOST_FS_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_L4PER_MOD */
+ {.mod_off = OMAP4430_CM2_L4PER_INST, .no_reg = 51,
+ {{.addr = OMAP4_CM_L4PER_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_L4PER_ADC_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_ELM_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_HECC1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_HECC2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCASP2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCASP3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MGATE_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MSPROHG_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_SLIMBUS2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4PER_I2C5_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_STATICDEP_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_DYNAMICDEP_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_AES1_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_AES2_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_DES3DES_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_PKAEIP29_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_RNG_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET},
+ {.addr = OMAP4_CM_L4SEC_CRYPTODMA_CLKCTRL_OFFSET} },
+ },
+ /* OMAP4430_CM2_CEFUSE_MOD */
+ {.mod_off = OMAP4430_CM2_CEFUSE_INST, .no_reg = 2,
+ {{.addr = OMAP4_CM_CEFUSE_CLKSTCTRL_OFFSET},
+ {.addr = OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET} },
+ },
+};
+
+static void omap4_cm1_prepare_off(void)
+{
+ u32 i, j;
+ struct omap4_cm_regs *cm_reg = cm1_regs;
+
+ for (i = 0; i < ARRAY_SIZE(cm1_regs); i++, cm_reg++) {
+ for (j = 0; j < cm_reg->no_reg; j++) {
+ cm_reg->reg[j].val =
+ omap4_cminst_read_inst_reg(OMAP4430_CM1_PARTITION,
+ cm_reg->mod_off,
+ cm_reg->reg[j].addr);
+ }
+ }
+}
+
+static void omap4_cm2_prepare_off(void)
+{
+ u32 i, j;
+ struct omap4_cm_regs *cm_reg = cm2_regs;
+
+ for (i = 0; i < ARRAY_SIZE(cm2_regs); i++, cm_reg++) {
+ for (j = 0; j < cm_reg->no_reg; j++) {
+ cm_reg->reg[j].val =
+ omap4_cminst_read_inst_reg(OMAP4430_CM2_PARTITION,
+ cm_reg->mod_off,
+ cm_reg->reg[j].addr);
+ }
+ }
+}
+
+static void omap4_cm1_resume_off(void)
+{
+ u32 i, j;
+ struct omap4_cm_regs *cm_reg = cm1_regs;
+
+ for (i = 0; i < ARRAY_SIZE(cm1_regs); i++, cm_reg++) {
+ for (j = 0; j < cm_reg->no_reg; j++) {
+ omap4_cminst_write_inst_reg(cm_reg->reg[j].val,
+ OMAP4430_CM1_PARTITION,
+ cm_reg->mod_off,
+ cm_reg->reg[j].addr);
+ }
+ }
+}
+
+static void omap4_cm2_resume_off(void)
+{
+ u32 i, j;
+ struct omap4_cm_regs *cm_reg = cm2_regs;
+
+ for (i = 0; i < ARRAY_SIZE(cm2_regs); i++, cm_reg++) {
+ for (j = 0; j < cm_reg->no_reg; j++) {
+ omap4_cminst_write_inst_reg(cm_reg->reg[j].val,
+ OMAP4430_CM2_PARTITION,
+ cm_reg->mod_off,
+ cm_reg->reg[j].addr);
+ }
+ }
+}
+
+void omap4_cm_prepare_off(void)
+{
+ omap4_cm1_prepare_off();
+ omap4_cm2_prepare_off();
+}
+
+void omap4_cm_resume_off(void)
+{
+ omap4_cm1_resume_off();
+ omap4_cm2_resume_off();
+}
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 0b87ec8..4124989 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -27,6 +27,10 @@
# ifndef __ASSEMBLER__
extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
+extern void omap4_cm_prepare_off(void);
+extern void omap4_cm_resume_off(void);
+extern void omap4_dpll_prepare_off(void);
+extern void omap4_dpll_resume_off(void);
# endif
#endif
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..ccebb26 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)
@@ -378,11 +379,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 +411,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/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 4bf6e6e..da13f2d 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -30,6 +30,7 @@
#include "powerdomain.h"
#include "clockdomain.h"
#include <plat/serial.h>
+#include <plat/omap-pm.h>
#include "pm.h"
#include "control.h"
@@ -119,7 +120,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
}
/* Execute ARM wfi */
- omap_sram_idle();
+ omap_sram_idle(false);
/* Re-allow idle for C1 */
if (state == &dev->states[0]) {
@@ -157,7 +158,7 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
u32 mpu_deepest_state = PWRDM_POWER_RET;
u32 core_deepest_state = PWRDM_POWER_RET;
- if (enable_off_mode) {
+ if (off_mode_enabled) {
mpu_deepest_state = PWRDM_POWER_OFF;
/*
* Erratum i583: valable for ES rev < Es1.2 on 3630.
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
new file mode 100644
index 0000000..4ddd08c
--- /dev/null
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -0,0 +1,747 @@
+/*
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/cpuidle.h>
+#include <linux/clockchips.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/cpu_pm.h>
+
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/hardware/gic.h>
+
+#include <mach/omap4-common.h>
+#include <mach/omap-wakeupgen.h>
+
+#include <plat/gpio.h>
+
+#include "clockdomain.h"
+#include "pm.h"
+#include "prm.h"
+
+#ifdef CONFIG_CPU_IDLE
+
+/* C1 is a single-cpu C-state, it can be entered by each cpu independently */
+/* C1 - CPUx WFI + MPU ON + CORE ON */
+#define OMAP4_STATE_C1 0
+/* C2 through C4 are shared C-states, both CPUs must agree to enter */
+/* C2 - CPU0 INA + CPU1 INA + 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 CSWR + CORE OSWR */
+#define OMAP4_STATE_C4 3
+
+#define OMAP4_MAX_STATES 4
+
+static bool disallow_smp_idle;
+module_param(disallow_smp_idle, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(disallow_smp_idle,
+ "Don't enter idle if multiple cpus are active");
+
+static bool skip_off;
+module_param(skip_off, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(skip_off,
+ "Do everything except actually enter the low power state (debugging)");
+
+static bool keep_core_on;
+module_param(keep_core_on, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(keep_core_on,
+ "Prevent core powerdomain from entering any low power states (debugging)");
+
+static bool keep_mpu_on;
+module_param(keep_mpu_on, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(keep_mpu_on,
+ "Prevent mpu powerdomain from entering any low power states (debugging)");
+
+static int max_state;
+module_param(max_state, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_state,
+ "Select deepest power state allowed (0=any, 1=WFI, 2=INA, 3=CSWR, 4=OSWR)");
+
+static int only_state;
+module_param(only_state, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(only_state,
+ "Select only power state allowed (0=any, 1=WFI, 2=INA, 3=CSWR, 4=OSWR)");
+
+static const int omap4_poke_interrupt[2] = {
+ OMAP44XX_IRQ_CPUIDLE_POKE0,
+ OMAP44XX_IRQ_CPUIDLE_POKE1
+};
+
+struct omap4_processor_cx {
+ u8 valid;
+ u8 type;
+ u32 exit_latency;
+ u32 target_residency;
+ u32 mpu_state;
+ u32 mpu_logic_state;
+ u32 core_state;
+ u32 core_logic_state;
+ const char *desc;
+};
+
+struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
+static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd;
+static struct omap4_processor_cx *omap4_idle_requested_cx[NR_CPUS];
+static int omap4_idle_ready_count;
+static DEFINE_SPINLOCK(omap4_idle_lock);
+static struct clockdomain *cpu1_cd;
+
+/*
+ * Raw measured exit latency numbers (us):
+ * state average max
+ * C2 383 1068
+ * C3 641 1190
+ * C4 769 1323
+ */
+
+static struct cpuidle_params cpuidle_params_table[] = {
+ /* C1 - CPUx WFI + MPU ON + CORE ON */
+ {.exit_latency = 2 + 2, .target_residency = 5, .valid = 1},
+ /* C2 - CPU0 INA + CPU1 INA + MPU INA + CORE INA */
+ {.exit_latency = 1100, .target_residency = 1100, .valid = 1},
+ /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE CSWR */
+ {.exit_latency = 1200, .target_residency = 1200, .valid = 1},
+#ifdef CONFIG_OMAP_ALLOW_OSWR
+ /* C4 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE OSWR */
+ {.exit_latency = 1500, .target_residency = 1500, .valid = 1},
+#else
+ {.exit_latency = 1500, .target_residency = 1500, .valid = 0},
+#endif
+};
+
+static void omap4_update_actual_state(struct cpuidle_device *dev,
+ struct omap4_processor_cx *cx)
+{
+ int i;
+
+ for (i = 0; i < dev->state_count; i++) {
+ if (dev->states[i].driver_data == cx) {
+ dev->last_state = &dev->states[i];
+ return;
+ }
+ }
+}
+
+static bool omap4_gic_interrupt_pending(void)
+{
+ void __iomem *gic_cpu = omap4_get_gic_cpu_base();
+
+ return (__raw_readl(gic_cpu + GIC_CPU_HIGHPRI) != 0x3FF);
+}
+
+/**
+ * omap4_wfi_until_interrupt
+ *
+ * wfi can sometimes return with no interrupts pending, for example on a
+ * broadcast cache flush or tlb op. This function will call wfi repeatedly
+ * until an interrupt is actually pending. Returning without looping would
+ * cause very short idle times to be reported to the idle governor, messing
+ * with repeating interrupt detection, and causing deep idle states to be
+ * avoided.
+ */
+static void omap4_wfi_until_interrupt(void)
+{
+retry:
+ omap_do_wfi();
+
+ if (!omap4_gic_interrupt_pending())
+ goto retry;
+}
+
+/**
+ * omap4_idle_wait
+ *
+ * similar to WFE, but can be woken by an interrupt even though interrupts
+ * are masked. An "event" is emulated by per-cpu unused interrupt in the GIC.
+ * Returns false if wake caused by an interrupt, true if by an "event".
+ */
+static bool omap4_idle_wait(void)
+{
+ int cpu = hard_smp_processor_id();
+ void __iomem *gic_dist = omap4_get_gic_dist_base();
+ u32 bit = BIT(omap4_poke_interrupt[cpu] % 32);
+ u32 reg = (omap4_poke_interrupt[cpu] / 32) * 4;
+ bool poked;
+
+ /* Unmask the "event" interrupt */
+ __raw_writel(bit, gic_dist + GIC_DIST_ENABLE_SET + reg);
+
+ omap4_wfi_until_interrupt();
+
+ /* Read the "event" interrupt pending bit */
+ poked = __raw_readl(gic_dist + GIC_DIST_PENDING_SET + reg) & bit;
+
+ /* Mask the "event" */
+ __raw_writel(bit, gic_dist + GIC_DIST_ENABLE_CLEAR + reg);
+
+ /* Clear the event */
+ if (poked)
+ __raw_writel(bit, gic_dist + GIC_DIST_PENDING_CLEAR + reg);
+
+ return poked;
+}
+
+/**
+ * omap4_poke_cpu
+ * @cpu: cpu to wake
+ *
+ * trigger an "event" to wake a cpu from omap4_idle_wait.
+ */
+static void omap4_poke_cpu(int cpu)
+{
+ void __iomem *gic_dist = omap4_get_gic_dist_base();
+ u32 bit = BIT(omap4_poke_interrupt[cpu] % 32);
+ u32 reg = (omap4_poke_interrupt[cpu] / 32) * 4;
+
+ __raw_writel(bit, gic_dist + GIC_DIST_PENDING_SET + reg);
+}
+
+/**
+ * omap4_enter_idle
+ * @dev: cpuidle device
+ * @state: The target state to be programmed
+ *
+ * Idle function for C1 state, WFI on a single CPU.
+ * Called with irqs off, returns with irqs on.
+ * Returns the amount of time spent in the low power state.
+ */
+static int omap4_enter_idle_wfi(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ ktime_t preidle, postidle;
+
+ local_fiq_disable();
+
+ preidle = ktime_get();
+
+ omap4_wfi_until_interrupt();
+
+ postidle = ktime_get();
+
+ local_fiq_enable();
+ local_irq_enable();
+
+ omap4_update_actual_state(dev, &omap4_power_states[OMAP4_STATE_C1]);
+
+ return ktime_to_us(ktime_sub(postidle, preidle));
+}
+
+static inline bool omap4_all_cpus_idle(void)
+{
+ int i;
+
+ assert_spin_locked(&omap4_idle_lock);
+
+ for_each_online_cpu(i)
+ if (omap4_idle_requested_cx[i] == NULL)
+ return false;
+
+ return true;
+}
+
+static inline struct omap4_processor_cx *omap4_get_idle_state(void)
+{
+ struct omap4_processor_cx *cx = NULL;
+ int i;
+
+ assert_spin_locked(&omap4_idle_lock);
+
+ for_each_online_cpu(i)
+ if (!cx || omap4_idle_requested_cx[i]->type < cx->type)
+ cx = omap4_idle_requested_cx[i];
+
+ return cx;
+}
+
+static void omap4_cpu_poke_others(int cpu)
+{
+ int i;
+
+ for_each_online_cpu(i)
+ if (i != cpu)
+ omap4_poke_cpu(i);
+}
+
+static void omap4_cpu_update_state(int cpu, struct omap4_processor_cx *cx)
+{
+ assert_spin_locked(&omap4_idle_lock);
+
+ omap4_idle_requested_cx[cpu] = cx;
+ omap4_cpu_poke_others(cpu);
+}
+
+/**
+ * omap4_enter_idle_primary
+ * @cx: target idle state
+ *
+ * Waits for cpu1 to be off, then starts the transition to the target power
+ * state for cpu0, mpu and core power domains.
+ */
+static void omap4_enter_idle_primary(struct omap4_processor_cx *cx)
+{
+ int cpu = 0;
+ int ret;
+ int count = 1000000;
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+
+ cpu_pm_enter();
+
+ if (!keep_mpu_on) {
+ pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
+ omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
+ }
+
+ if (!keep_core_on) {
+ pwrdm_set_logic_retst(core_pd, cx->core_logic_state);
+ omap_set_pwrdm_state(core_pd, cx->core_state);
+ }
+
+ if (skip_off)
+ goto out;
+
+ /* spin until cpu1 is really off */
+ while ((pwrdm_read_pwrst(cpu1_pd) != PWRDM_POWER_OFF) && count--)
+ cpu_relax();
+
+ if (pwrdm_read_pwrst(cpu1_pd) != PWRDM_POWER_OFF)
+ goto wake_cpu1;
+
+ ret = pwrdm_wait_transition(cpu1_pd);
+ if (ret)
+ goto wake_cpu1;
+
+ pr_debug("%s: cpu0 down\n", __func__);
+
+ omap4_enter_sleep(0, PWRDM_POWER_OFF, false);
+
+ pr_debug("%s: cpu0 up\n", __func__);
+
+ /* 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);
+
+wake_cpu1:
+ if (!cpu_is_offline(1)) {
+ /*
+ * Work around a ROM bug that causes CPU1 to corrupt the
+ * gic distributor enable register on 4460 by disabling
+ * the gic distributor before waking CPU1, and then waiting
+ * for CPU1 to re-enable the gic distributor before continuing.
+ */
+ if (!cpu_is_omap443x())
+ gic_dist_disable();
+
+ clkdm_wakeup(cpu1_cd);
+
+ if (!cpu_is_omap443x())
+ while (gic_dist_disabled())
+ cpu_relax();
+
+ /*
+ * cpu1 mucks with page tables while it is starting,
+ * prevent cpu0 executing any processes until cpu1 is up
+ */
+ while (omap4_idle_requested_cx[1] && omap4_idle_ready_count)
+ cpu_relax();
+ }
+
+out:
+ cpu_pm_exit();
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+}
+
+/**
+ * omap4_enter_idle_secondary
+ * @cpu: target cpu number
+ *
+ * Puts target cpu powerdomain into OFF.
+ */
+static void omap4_enter_idle_secondary(int cpu)
+{
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+
+ cpu_pm_enter();
+
+ pr_debug("%s: cpu1 down\n", __func__);
+ flush_cache_all();
+ dsb();
+
+ /* TODO: merge CPU1 wakeup masks into CPU0 */
+ omap_wakeupgen_irqmask_all(cpu, 1);
+ gic_cpu_disable();
+
+ if (!skip_off)
+ omap4_enter_lowpower(cpu, PWRDM_POWER_OFF);
+
+ omap_wakeupgen_irqmask_all(cpu, 0);
+ gic_cpu_enable();
+
+ pr_debug("%s: cpu1 up\n", __func__);
+
+ cpu_pm_exit();
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+}
+
+/**
+ * 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.
+ * Called with irqs off, returns with irqs on.
+ * 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 omap4_processor_cx *actual_cx;
+ ktime_t preidle, postidle;
+ bool idle = true;
+ int cpu = dev->cpu;
+
+ /*
+ * If disallow_smp_idle is set, revert to the old hotplug governor
+ * behavior
+ */
+ if (dev->cpu != 0 && disallow_smp_idle)
+ return omap4_enter_idle_wfi(dev, state);
+
+ /* Clamp the power state at max_state */
+ if (max_state > 0 && (cx->type > max_state - 1))
+ cx = &omap4_power_states[max_state - 1];
+
+ /*
+ * If only_state is set, use wfi if asking for a shallower idle state,
+ * or the specified state if asking for a deeper idle state
+ */
+ if (only_state > 0) {
+ if (cx->type < only_state - 1)
+ cx = &omap4_power_states[OMAP4_STATE_C1];
+ else
+ cx = &omap4_power_states[only_state - 1];
+ }
+
+ if (cx->type == OMAP4_STATE_C1)
+ return omap4_enter_idle_wfi(dev, state);
+
+ preidle = ktime_get();
+
+ local_fiq_disable();
+
+ actual_cx = &omap4_power_states[OMAP4_STATE_C1];
+
+ spin_lock(&omap4_idle_lock);
+ omap4_cpu_update_state(cpu, cx);
+
+ /* Wait for both cpus to be idle, exiting if an interrupt occurs */
+ while (idle && !omap4_all_cpus_idle()) {
+ spin_unlock(&omap4_idle_lock);
+ idle = omap4_idle_wait();
+ spin_lock(&omap4_idle_lock);
+ }
+
+ /*
+ * If we waited for longer than a millisecond, pop out to the governor
+ * to let it recalculate the desired state.
+ */
+ if (ktime_to_us(ktime_sub(preidle, ktime_get())) > 1000)
+ idle = false;
+
+ if (!idle) {
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+ goto out;
+ }
+
+ /*
+ * If we go to sleep with an IPI pending, we will lose it. Once we
+ * reach this point, the other cpu is either already idle or will
+ * shortly abort idle. If it is already idle it can't send us an IPI,
+ * so it is safe to check for pending IPIs here. If it aborts idle
+ * we will abort as well, and any future IPIs will be processed.
+ */
+ if (omap4_gic_interrupt_pending()) {
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+ goto out;
+ }
+
+ /*
+ * Both cpus are probably idle. There is a small chance the other cpu
+ * just became active. cpu 0 will set omap4_idle_ready_count to 1,
+ * then each other cpu will increment it. Once a cpu has incremented
+ * the count, it cannot abort idle and must spin until either the count
+ * has hit num_online_cpus(), or is reset to 0 by an aborting cpu.
+ */
+ if (cpu == 0) {
+ BUG_ON(omap4_idle_ready_count != 0);
+ /* cpu0 requests shared-OFF */
+ omap4_idle_ready_count = 1;
+ /* cpu0 can no longer abort shared-OFF, but cpu1 can */
+
+ /* wait for cpu1 to ack shared-OFF, or leave idle */
+ while (omap4_idle_ready_count != num_online_cpus() &&
+ omap4_idle_ready_count != 0 && omap4_all_cpus_idle()) {
+ spin_unlock(&omap4_idle_lock);
+ cpu_relax();
+ spin_lock(&omap4_idle_lock);
+ }
+
+ if (omap4_idle_ready_count != num_online_cpus() ||
+ !omap4_all_cpus_idle()) {
+ pr_debug("%s: cpu1 aborted: %d %p\n", __func__,
+ omap4_idle_ready_count,
+ omap4_idle_requested_cx[1]);
+ omap4_idle_ready_count = 0;
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+ goto out;
+ }
+
+ actual_cx = omap4_get_idle_state();
+ spin_unlock(&omap4_idle_lock);
+
+ /* cpu1 is turning itself off, continue with turning cpu0 off */
+
+ omap4_enter_idle_primary(actual_cx);
+
+ spin_lock(&omap4_idle_lock);
+ omap4_idle_ready_count = 0;
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+ } else {
+ /* wait for cpu0 to request the shared-OFF, or leave idle */
+ while ((omap4_idle_ready_count == 0) && omap4_all_cpus_idle()) {
+ spin_unlock(&omap4_idle_lock);
+ cpu_relax();
+ spin_lock(&omap4_idle_lock);
+ }
+
+ if (!omap4_all_cpus_idle()) {
+ pr_debug("%s: cpu0 aborted: %d %p\n", __func__,
+ omap4_idle_ready_count,
+ omap4_idle_requested_cx[0]);
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+ goto out;
+ }
+
+ pr_debug("%s: cpu1 acks\n", __func__);
+ /* ack shared-OFF */
+ if (omap4_idle_ready_count > 0)
+ omap4_idle_ready_count++;
+ BUG_ON(omap4_idle_ready_count > num_online_cpus());
+
+ while (omap4_idle_ready_count != num_online_cpus() &&
+ omap4_idle_ready_count != 0) {
+ spin_unlock(&omap4_idle_lock);
+ cpu_relax();
+ spin_lock(&omap4_idle_lock);
+ }
+
+ if (omap4_idle_ready_count == 0) {
+ pr_debug("%s: cpu0 aborted: %d %p\n", __func__,
+ omap4_idle_ready_count,
+ omap4_idle_requested_cx[0]);
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+ goto out;
+ }
+
+ /* cpu1 can no longer abort shared-OFF */
+
+ actual_cx = omap4_get_idle_state();
+ spin_unlock(&omap4_idle_lock);
+
+ omap4_enter_idle_secondary(cpu);
+
+ spin_lock(&omap4_idle_lock);
+ omap4_idle_ready_count = 0;
+ omap4_cpu_update_state(cpu, NULL);
+ spin_unlock(&omap4_idle_lock);
+
+ clkdm_allow_idle(cpu1_cd);
+
+ }
+
+out:
+ postidle = ktime_get();
+
+ omap4_update_actual_state(dev, actual_cx);
+
+ local_irq_enable();
+ local_fiq_enable();
+
+ return ktime_to_us(ktime_sub(postidle, preidle));
+}
+
+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].desc = "CPU WFI";
+
+ /*
+ * 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].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].desc = "CPUs OFF, MPU + 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].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].desc = "CPUs OFF, MPU + CORE CSWR";
+
+ /*
+ * C4 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE OSWR
+ */
+ 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].mpu_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C4].mpu_logic_state = PWRDM_POWER_RET;
+ 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].desc = "CPUs OFF, MPU CSWR + CORE OSWR";
+
+}
+
+struct cpuidle_driver omap4_idle_driver = {
+ .name = "omap4_idle",
+ .owner = THIS_MODULE,
+};
+
+/**
+ * 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;
+ struct omap4_processor_cx *cx;
+ struct cpuidle_state *state;
+ struct cpuidle_device *dev;
+
+ mpu_pd = pwrdm_lookup("mpu_pwrdm");
+ BUG_ON(!mpu_pd);
+ cpu1_pd = pwrdm_lookup("cpu1_pwrdm");
+ BUG_ON(!cpu1_pd);
+ cpu1_cd = clkdm_lookup("mpu1_clkdm");
+ BUG_ON(!cpu1_cd);
+ core_pd = pwrdm_lookup("core_pwrdm");
+ BUG_ON(!core_pd);
+
+ omap4_init_power_states();
+ cpuidle_register_driver(&omap4_idle_driver);
+
+ for_each_possible_cpu(cpu_id) {
+ 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 = CPUIDLE_FLAG_TIME_VALID;
+ if (cx->type == OMAP4_STATE_C1) {
+ dev->safe_state = state;
+ state->enter = omap4_enter_idle_wfi;
+ } else {
+ state->enter = 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;
+
+ if (cpuidle_register_device(dev)) {
+ pr_err("%s: CPUidle register device failed\n", __func__);
+ return -EIO;
+ }
+
+ __raw_writeb(BIT(cpu_id), omap4_get_gic_dist_base() +
+ GIC_DIST_TARGET + omap4_poke_interrupt[cpu_id]);
+ }
+
+ 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 5b8ca68..cf7a0ba 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -29,13 +29,18 @@
#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>
+#include <plat/mcpdm.h>
+
+#include <sound/omap-abe-dsp.h>
#include "mux.h"
#include "control.h"
#include "devices.h"
+#include "dvfs.h"
#define L3_MODULES_MAX_LEN 12
#define L3_MODULES 3
@@ -292,6 +297,112 @@ static inline void omap_init_mbox(void) { }
static inline void omap_init_sti(void) {}
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+ defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
+
+static struct omap_device_pm_latency omap_mcpdm_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+static void omap_init_mcpdm(void)
+{
+ struct omap_hwmod *oh;
+ struct omap_device *od;
+ struct omap_mcpdm_platform_data *pdata;
+ char *oh_name = "mcpdm";
+ char *dev_name = "omap-mcpdm";
+
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ pr_err("%s: could not look up %s\n", __func__, oh_name);
+ return;
+ }
+
+ pdata = kzalloc(sizeof(struct omap_mcpdm_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: could not allocate platform data\n", __func__);
+ return;
+ }
+
+ pdata->was_context_lost = omap_pm_was_context_lost;
+
+ od = omap_device_build(dev_name, -1, oh, pdata,
+ sizeof(struct omap_mcpdm_platform_data),
+ omap_mcpdm_latency,
+ ARRAY_SIZE(omap_mcpdm_latency), 0);
+ WARN(IS_ERR(od), "could not build omap_device for %s:%s\n",
+ oh_name, dev_name);
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
+#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;
+ char *oh_name = "aess";
+ char *dev_name = "aess";
+
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ pr_err("%s: could not look up %s\n", __func__, oh_name);
+ return;
+ }
+
+ pdata = kzalloc(sizeof(struct omap4_abe_dsp_pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: could not allocate platform data\n", __func__);
+ return;
+ }
+
+ pdata->device_scale = omap_device_scale;
+ pdata->was_context_lost = omap_pm_was_context_lost;
+
+ od = omap_device_build(dev_name, -1, oh, pdata,
+ sizeof(struct omap4_abe_dsp_pdata),
+ omap_aess_latency,
+ ARRAY_SIZE(omap_aess_latency), 0);
+ WARN(IS_ERR(od), "could not build omap_device for %s:%s\n",
+ oh_name, dev_name);
+
+ kfree(pdata);
+}
+#else
+static inline void omap_init_aess(void) {}
+#endif
+
+#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 = {
@@ -300,6 +411,14 @@ static struct platform_device omap_pcm = {
};
/*
+ * Device for the ASoC OMAP4 HDMI machine driver
+ */
+static struct platform_device omap4_hdmi_audio = {
+ .name = "omap4-hdmi-audio",
+ .id = -1,
+};
+
+/*
* OMAP2420 has 2 McBSP ports
* OMAP2430 has 5 McBSP ports
* OMAP3 has 5 McBSP ports
@@ -313,6 +432,31 @@ OMAP_MCBSP_PLATFORM_DEVICE(5);
static void omap_init_audio(void)
{
+ struct omap_hwmod *oh_hdmi;
+ struct omap_device *od_hdmi, *od_hdmi_codec;
+ char *oh_hdmi_name = "dss_hdmi";
+ char *dev_hdmi_name = "hdmi-audio-dai";
+ char *dev_hdmi_codec_name = "omap-hdmi-codec";
+
+ if (cpu_is_omap44xx()) {
+ oh_hdmi = omap_hwmod_lookup(oh_hdmi_name);
+ WARN(!oh_hdmi, "%s: could not find omap_hwmod for %s\n",
+ __func__, oh_hdmi_name);
+
+ od_hdmi = omap_device_build(dev_hdmi_name, -1, oh_hdmi, NULL, 0,
+ NULL, 0, false);
+ WARN(IS_ERR(od_hdmi), "%s: could not build omap_device for %s\n",
+ __func__, dev_hdmi_name);
+
+ od_hdmi_codec = omap_device_build(dev_hdmi_codec_name,
+ -1, oh_hdmi, NULL, 0, NULL, 0, false);
+
+ WARN(IS_ERR(od_hdmi_codec), "%s: could not build omap_device for %s\n",
+ __func__, dev_hdmi_codec_name);
+
+ platform_device_register(&omap4_hdmi_audio);
+ }
+
platform_device_register(&omap_mcbsp1);
platform_device_register(&omap_mcbsp2);
if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
@@ -329,6 +473,39 @@ static void omap_init_audio(void)
static inline void omap_init_audio(void) {}
#endif
+#if defined(CONFIG_SND_OMAP_SOC_MCASP) || \
+ defined(CONFIG_SND_OMAP_SOC_MCASP_MODULE)
+static struct omap_device_pm_latency omap_mcasp_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+static void omap_init_mcasp(void)
+{
+ struct omap_hwmod *oh;
+ struct omap_device *od;
+ char *oh_name = "omap-mcasp-dai";
+ char *dev_name = "omap-mcasp-dai";
+
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ pr_err("%s: could not look up %s\n", __func__, oh_name);
+ return;
+ }
+
+ od = omap_device_build(dev_name, -1, oh, NULL, 0,
+ omap_mcasp_latency,
+ ARRAY_SIZE(omap_mcasp_latency), 0);
+ WARN(IS_ERR(od), "could not build omap_device for %s:%s\n",
+ oh_name, dev_name);
+}
+#else
+static inline void omap_init_mcasp(void) {}
+#endif
+
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
#include <plat/mcspi.h>
@@ -673,6 +850,68 @@ 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_scale = omap_device_scale;
+ pdata->device_enable = omap_device_enable;
+ pdata->device_idle = omap_device_idle;
+ pdata->device_shutdown = omap_device_shutdown;
+
+ pdata->ovfreqs = 0;
+ if (cpu_is_omap446x())
+ pdata->ovfreqs = 1;
+
+ 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,9 +920,13 @@ 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_mcpdm();
+ omap_init_aess();
+ omap_init_abe();
omap_init_audio();
omap_init_camera();
omap_init_mbox();
+ omap_init_mcasp();
omap_init_mcspi();
omap_init_pmu();
omap_hdq_init();
@@ -691,6 +934,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/display.c b/arch/arm/mach-omap2/display.c
index 543fcb8..dd91c20 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -25,6 +25,7 @@
#include <video/omapdss.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
static struct platform_device omap_display_device = {
.name = "omapdss",
@@ -42,20 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
},
};
-/* oh_core is used for getting opt-clocks */
-static struct omap_hwmod *oh_core;
-
-static bool opt_clock_available(const char *clk_role)
-{
- int i;
-
- for (i = 0; i < oh_core->opt_clks_cnt; i++) {
- if (!strcmp(oh_core->opt_clks[i].role, clk_role))
- return true;
- }
- return false;
-}
-
struct omap_dss_hwmod_data {
const char *oh_name;
const char *dev_name;
@@ -109,16 +96,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
}
- /* opt_clks are always associated with dss hwmod */
- oh_core = omap_hwmod_lookup("dss_core");
- if (!oh_core) {
- pr_err("Could not look up dss_core.\n");
- return -ENODEV;
- }
-
pdata.board_data = board_data;
- pdata.board_data->get_last_off_on_transaction_id = NULL;
- pdata.opt_clock_available = opt_clock_available;
for (i = 0; i < oh_count; i++) {
oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-omap2/dmtimer.c
new file mode 100644
index 0000000..e9cba71
--- /dev/null
+++ b/arch/arm/mach-omap2/dmtimer.c
@@ -0,0 +1,283 @@
+/**
+ * OMAP2+ Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which extracts timers
+ * information from hwmod database and registers with linux device model.
+ * It also has low level function to change the timer input clock source.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <plat/dmtimer.h>
+#include <plat/omap_device.h>
+#include <plat/cpu.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
+
+static u8 __initdata system_timer_id;
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev: timer platform device pointer
+ * @source: array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+ int ret;
+ struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+ struct clk *new_fclk;
+ char *fclk_name = "32k_ck"; /* default name */
+
+ struct clk *fclk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR_OR_NULL(fclk)) {
+ dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case OMAP_TIMER_SRC_SYS_CLK:
+ fclk_name = "sys_ck";
+ break;
+
+ case OMAP_TIMER_SRC_32_KHZ:
+ fclk_name = "32k_ck";
+ break;
+
+ case OMAP_TIMER_SRC_EXT_CLK:
+ if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
+ fclk_name = "alt_ck";
+ break;
+ }
+ default:
+ dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+ __func__, __LINE__);
+ clk_put(fclk);
+ return -EINVAL;
+ }
+
+ new_fclk = clk_get(&pdev->dev, fclk_name);
+ if (IS_ERR_OR_NULL(new_fclk)) {
+ dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+ __func__, __LINE__, fclk_name);
+ clk_put(fclk);
+ return -EINVAL;
+ }
+
+ ret = clk_set_parent(fclk, new_fclk);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+ __func__, fclk_name);
+ ret = -EINVAL;
+ }
+
+ clk_put(new_fclk);
+ clk_put(fclk);
+
+ return ret;
+}
+
+struct omap_device_pm_latency omap2_dmtimer_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh: timer hwmod pointer to be used to build timer device
+ * @user: parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+ int id;
+ int ret = 0;
+ char *name = "omap_timer";
+ struct dmtimer_platform_data *pdata;
+ struct omap_device *od;
+ struct omap_secure_timer_dev_attr *secure_timer_dev_attr;
+ struct powerdomain *pwrdm;
+
+ /*
+ * Extract the IDs from name field in hwmod database
+ * and use the same for constructing ids' for the
+ * timer devices. In a way, we are avoiding usage of
+ * static variable witin the function to do the same.
+ * CAUTION: We have to be careful and make sure the
+ * name in hwmod database does not change in which case
+ * we might either make corresponding change here or
+ * switch back static variable mechanism.
+ */
+ sscanf(oh->name, "timer%2d", &id);
+ if (unlikely(id == system_timer_id))
+ return ret;
+
+ pr_debug("%s: %s\n", __func__, oh->name);
+
+ /* do not register secure timer */
+ secure_timer_dev_attr = oh->dev_attr;
+ if (secure_timer_dev_attr && secure_timer_dev_attr->is_secure_timer)
+ return ret;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+ return -ENOMEM;
+ }
+ pdata->set_timer_src = omap2_dm_timer_set_src;
+ pdata->timer_ip_type = oh->class->rev;
+ pwrdm = omap_hwmod_get_pwrdm(oh);
+ if (!pwrdm) {
+ pr_debug("%s: could not find pwrdm for (%s) in omap hwmod!\n",
+ __func__, oh->name);
+ return -EINVAL;
+ }
+ pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+
+ od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+ omap2_dmtimer_latency,
+ ARRAY_SIZE(omap2_dmtimer_latency),
+ pdata->is_early_init);
+
+ if (IS_ERR(od)) {
+ pr_err("%s: Can't build omap_device for %s: %s.\n",
+ __func__, name, oh->name);
+ ret = -EINVAL;
+ }
+
+ kfree(pdata);
+
+ return ret;
+}
+
+/**
+ * omap2_system_timer_init - top level system timer initialization
+ * called from omap2_gp_timer_init() in timer-gp.c
+ * @id : system timer id
+ *
+ * This function does hwmod setup for the system timer entry needed
+ * prior to building and registering the device. After the device is
+ * registered early probe initiated.
+ */
+int __init omap2_system_timer_init(u8 id)
+{
+ int ret = 0;
+ char *name = "omap_timer";
+ struct dmtimer_platform_data *pdata;
+ struct omap_device *od;
+ struct omap_hwmod *oh;
+ char system_timer_name[8]; /* 8 = sizeof("timerXX0") */
+
+ system_timer_id = id;
+
+ sprintf(system_timer_name, "timer%d", id);
+ ret = omap_hwmod_setup_one(system_timer_name);
+ if (ret) {
+ pr_err("%s: omap_hwmod_setup_one(%s) failed.\n",
+ __func__, system_timer_name);
+ return ret;
+ }
+ oh = omap_hwmod_lookup(system_timer_name);
+ if (!oh) {
+ pr_debug("%s: could not find (%s) in omap_hwmod_list!\n",
+ __func__, system_timer_name);
+ return -EINVAL;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+ return -ENOMEM;
+ }
+ pdata->is_early_init = 1;
+ pdata->set_timer_src = omap2_dm_timer_set_src;
+ pdata->timer_ip_type = oh->class->rev;
+ pdata->needs_manual_reset = 0;
+
+ od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+ omap2_dmtimer_latency,
+ ARRAY_SIZE(omap2_dmtimer_latency),
+ pdata->is_early_init);
+
+ if (IS_ERR(od)) {
+ pr_err("%s: Can't build omap_device for %s: %s.\n",
+ __func__, name, oh->name);
+ ret = -EINVAL;
+ }
+
+ kfree(pdata);
+
+ if (!ret) {
+ early_platform_driver_register_all("earlytimer");
+ early_platform_driver_probe("earlytimer", 1, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * omap2_system_timer_set_src - change the timer input clock source
+ * Allow system timer to program clock source before pm_runtime
+ * framework is available during system boot.
+ * @timer: pointer to struct omap_dm_timer
+ * @source: array index of parent clock source
+ */
+int __init omap2_system_timer_set_src(struct omap_dm_timer *timer, int source)
+{
+ int ret;
+
+ if (IS_ERR_OR_NULL(timer) || IS_ERR_OR_NULL(timer->fclk))
+ return -EINVAL;
+
+ clk_disable(timer->fclk);
+ ret = omap2_dm_timer_set_src(timer->pdev, source);
+ clk_enable(timer->fclk);
+
+ return ret;
+}
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+ int ret;
+
+ ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+ if (unlikely(ret)) {
+ pr_err("%s: device registration failed.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff --git a/arch/arm/mach-omap2/dmtimer.h b/arch/arm/mach-omap2/dmtimer.h
new file mode 100644
index 0000000..4cfd580
--- /dev/null
+++ b/arch/arm/mach-omap2/dmtimer.h
@@ -0,0 +1,32 @@
+/**
+ * OMAP Dual-Mode Timers - early initialization interface
+ *
+ * Function interface called first to start dmtimer early initialization.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_OMAP2_DMTIMER_H
+#define __ASM_ARCH_OMAP2_DMTIMER_H
+
+#include <plat/dmtimer.h>
+
+/*
+ * dmtimer is required during early part of boot sequence even before
+ * device model and pm_runtime if fully up and running. This function
+ * is called from following sequence:
+ * start_kernel()->time_init()->timer->init()->omap2_gp_timer_init()
+ */
+extern int __init omap2_system_timer_init(u8 id);
+extern int __init omap2_system_timer_set_src(struct omap_dm_timer *, int);
+#endif
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index f77022b..7fb0d21 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -32,8 +32,10 @@
#include <plat/clock.h>
#include "clock.h"
+#include "cm2_44xx.h"
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
+#include "cm-regbits-44xx.h"
/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
#define DPLL_AUTOIDLE_DISABLE 0x0
@@ -61,22 +63,76 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
{
const struct dpll_data *dd;
- int i = 0;
+ int i;
int ret = -EINVAL;
+ bool first_time = true;
+ u32 reg;
+ u32 orig_cm_div_m2_dpll_usb;
+ u32 orig_cm_clkdcoldo_dpll_usb;
+retry:
dd = clk->dpll_data;
state <<= __ffs(dd->idlest_mask);
+ i = 0;
while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
i < MAX_DPLL_WAIT_TRIES) {
i++;
udelay(1);
}
+ /* restore back old values if hit work-around */
+ if (!first_time) {
+ __raw_writel(orig_cm_div_m2_dpll_usb,
+ OMAP4430_CM_DIV_M2_DPLL_USB);
+ __raw_writel(orig_cm_clkdcoldo_dpll_usb,
+ OMAP4430_CM_CLKDCOLDO_DPLL_USB);
+ }
+
if (i == MAX_DPLL_WAIT_TRIES) {
printk(KERN_ERR "clock: %s failed transition to '%s'\n",
clk->name, (state) ? "locked" : "bypassed");
+
+ /* Try Error Recovery: for failing usbdpll locking */
+ if (!strcmp(clk->name, "dpll_usb_ck")) {
+
+ reg = __raw_readl(dd->mult_div1_reg);
+
+ /* Put in MN bypass */
+ _omap3_dpll_write_clken(clk, DPLL_MN_BYPASS);
+ i = 0;
+ while (!(__raw_readl(dd->idlest_reg) & (1 << OMAP4430_ST_MN_BYPASS_SHIFT)) &&
+ i < MAX_DPLL_WAIT_TRIES) {
+ i++;
+ udelay(1);
+ }
+
+ /* MN bypass looses contents of CM_CLKSEL_DPLL_USB */
+ __raw_writel(reg, dd->mult_div1_reg);
+
+ /* Force generate request to PRCM: put in Force mode */
+
+ /* a) CM_DIV_M2_DPLL_USB.DPLL_CLKOUT_GATE_CTRL = 1 */
+ orig_cm_div_m2_dpll_usb = __raw_readl(OMAP4430_CM_DIV_M2_DPLL_USB);
+ __raw_writel(orig_cm_div_m2_dpll_usb |
+ (1 << OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT),
+ OMAP4430_CM_DIV_M2_DPLL_USB);
+
+ /* b) CM_CLKDCOLDO_DPLL_USB.DPLL_CLKDCOLDO_GATE_CTRL = 1 */
+ orig_cm_clkdcoldo_dpll_usb = __raw_readl(OMAP4430_CM_CLKDCOLDO_DPLL_USB);
+ __raw_writel(orig_cm_clkdcoldo_dpll_usb |
+ (1 << OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT),
+ OMAP4430_CM_CLKDCOLDO_DPLL_USB);
+
+ /* Put back to locked mode */
+ _omap3_dpll_write_clken(clk, DPLL_LOCKED);
+
+ if (first_time) {
+ first_time = false;
+ goto retry;
+ }
+ }
} else {
pr_debug("clock: %s transition to '%s' in %d loops\n",
clk->name, (state) ? "locked" : "bypassed", i);
@@ -135,11 +191,20 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
*/
static int _omap3_noncore_dpll_lock(struct clk *clk)
{
+ const struct dpll_data *dd;
u8 ai;
- int r;
+ u8 state = 1;
+ int r = 0;
pr_debug("clock: locking DPLL %s\n", clk->name);
+ dd = clk->dpll_data;
+ state <<= __ffs(dd->idlest_mask);
+
+ /* Check if already locked */
+ if ((__raw_readl(dd->idlest_reg) & dd->idlest_mask) == state)
+ goto done;
+
ai = omap3_dpll_autoidle_read(clk);
omap3_dpll_deny_idle(clk);
@@ -151,6 +216,7 @@ static int _omap3_noncore_dpll_lock(struct clk *clk)
if (ai)
omap3_dpll_allow_idle(clk);
+done:
return r;
}
@@ -455,7 +521,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
new_parent = dd->clk_bypass;
} else {
if (dd->last_rounded_rate != rate)
- omap2_dpll_round_rate(clk, rate);
+ rate = clk->round_rate(clk, rate);
if (dd->last_rounded_rate == 0)
return -EINVAL;
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 4e4da61..d4cfe2a 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -14,12 +14,219 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/bitops.h>
-
+#include <linux/spinlock.h>
#include <plat/cpu.h>
#include <plat/clock.h>
+#include <plat/common.h>
+
+#include <mach/emif.h>
+#include <mach/omap4-common.h>
#include "clock.h"
+#include "clock44xx.h"
+#include "cm.h"
+#include "cm44xx.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "cminst44xx.h"
+#include "clock44xx.h"
+#include "clockdomain.h"
#include "cm-regbits-44xx.h"
+#include "prcm44xx.h"
+
+#define MAX_FREQ_UPDATE_TIMEOUT 100000
+
+static struct clockdomain *l3_emif_clkdm;
+static DEFINE_SPINLOCK(l3_emif_lock);
+
+/**
+ * omap4_core_dpll_m2_set_rate - set CORE DPLL M2 divider
+ * @clk: struct clk * of DPLL to set
+ * @rate: rounded target rate
+ *
+ * Programs the CM shadow registers to update CORE DPLL M2
+ * divider. M2 divider is used to clock external DDR and its
+ * reconfiguration on frequency change is managed through a
+ * hardware sequencer. This is managed by the PRCM with EMIF
+ * uding shadow registers.
+ * Returns -EINVAL/-1 on error and 0 on success.
+ */
+int omap4_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
+{
+ int i = 0;
+ u32 validrate = 0, shadow_freq_cfg1 = 0, new_div = 0;
+ unsigned long flags;
+
+ if (!clk || !rate)
+ return -EINVAL;
+
+ validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
+ if (validrate != rate)
+ return -EINVAL;
+
+ /* Just to avoid look-up on every call to speed up */
+ if (!l3_emif_clkdm) {
+ l3_emif_clkdm = clkdm_lookup("l3_emif_clkdm");
+ if (!l3_emif_clkdm) {
+ pr_err("%s: clockdomain lookup failed\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ spin_lock_irqsave(&l3_emif_lock, flags);
+
+ /* Configures MEMIF domain in SW_WKUP */
+ clkdm_wakeup(l3_emif_clkdm);
+
+ /*
+ * Errata ID: i728
+ *
+ * DESCRIPTION:
+ *
+ * If during a small window the following three events occur:
+ *
+ * 1) The EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM SR_TIMING counter expires
+ * 2) Frequency change update is requested CM_SHADOW_FREQ_CONFIG1
+ * FREQ_UPDATE set to 1
+ * 3) OCP access is requested
+ *
+ * There will be clock instability on the DDR interface.
+ *
+ * WORKAROUND:
+ *
+ * Prevent event 1) while event 2) is happening.
+ *
+ * Disable the self-refresh when requesting a frequency change.
+ * Before requesting a frequency change, program
+ * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0
+ * (omap_emif_frequency_pre_notify)
+ *
+ * When the frequency change is completed, reprogram
+ * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2.
+ * (omap_emif_frequency_post_notify)
+ */
+ omap_emif_frequency_pre_notify();
+
+ /*
+ * Program EMIF timing parameters in EMIF shadow registers
+ * for targetted DRR clock.
+ * DDR Clock = core_dpll_m2 / 2
+ */
+ omap_emif_setup_registers(validrate >> 1, LPDDR2_VOLTAGE_STABLE);
+
+ /*
+ * FREQ_UPDATE sequence:
+ * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden
+ * after CORE DPLL lock)
+ * - DLL_RESET=1 (DLL must be reset upon frequency change)
+ * - DPLL_CORE_M2_DIV with same value as the one already
+ * in direct register
+ * - DPLL_CORE_DPLL_EN=0x7 (to make CORE DPLL lock)
+ * - FREQ_UPDATE=1 (to start HW sequence)
+ */
+ shadow_freq_cfg1 = (1 << OMAP4430_DLL_RESET_SHIFT) |
+ (new_div << OMAP4430_DPLL_CORE_M2_DIV_SHIFT) |
+ (DPLL_LOCKED << OMAP4430_DPLL_CORE_DPLL_EN_SHIFT) |
+ (1 << OMAP4430_FREQ_UPDATE_SHIFT);
+ shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK;
+ __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1);
+
+ /* wait for the configuration to be applied */
+ omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1)
+ & OMAP4430_FREQ_UPDATE_MASK) == 0),
+ MAX_FREQ_UPDATE_TIMEOUT, i);
+
+ /* Re-enable DDR self refresh */
+ omap_emif_frequency_post_notify();
+
+ /* Configures MEMIF domain back to HW_WKUP */
+ clkdm_allow_idle(l3_emif_clkdm);
+
+ spin_unlock_irqrestore(&l3_emif_lock, flags);
+
+ if (i == MAX_FREQ_UPDATE_TIMEOUT) {
+ pr_err("%s: Frequency update for CORE DPLL M2 change failed\n",
+ __func__);
+ return -1;
+ }
+
+ /* Update the clock change */
+ clk->rate = validrate;
+
+ return 0;
+}
+
+
+/**
+ * omap4_prcm_freq_update - set freq_update bit
+ *
+ * Programs the CM shadow registers to update EMIF
+ * parametrs. Few usecase only few registers needs to
+ * be updated using prcm freq update sequence.
+ * EMIF read-idle control and zq-config needs to be
+ * updated for temprature alerts and voltage change
+ * Returns -1 on error and 0 on success.
+ */
+int omap4_prcm_freq_update(void)
+{
+ u32 shadow_freq_cfg1;
+ int i = 0;
+ unsigned long flags;
+
+ if (!l3_emif_clkdm) {
+ pr_err("%s: clockdomain lookup failed\n", __func__);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&l3_emif_lock, flags);
+ /* Configures MEMIF domain in SW_WKUP */
+ clkdm_wakeup(l3_emif_clkdm);
+
+ /* Disable DDR self refresh (Errata ID: i728) */
+ omap_emif_frequency_pre_notify();
+
+ /*
+ * FREQ_UPDATE sequence:
+ * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden
+ * after CORE DPLL lock)
+ * - FREQ_UPDATE=1 (to start HW sequence)
+ */
+ shadow_freq_cfg1 = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1);
+ shadow_freq_cfg1 |= (1 << OMAP4430_DLL_RESET_SHIFT) |
+ (1 << OMAP4430_FREQ_UPDATE_SHIFT);
+ shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK;
+ __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1);
+
+ /* wait for the configuration to be applied */
+ omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1)
+ & OMAP4430_FREQ_UPDATE_MASK) == 0),
+ MAX_FREQ_UPDATE_TIMEOUT, i);
+
+ /* Re-enable DDR self refresh */
+ omap_emif_frequency_post_notify();
+
+ /* Configures MEMIF domain back to HW_WKUP */
+ clkdm_allow_idle(l3_emif_clkdm);
+
+ spin_unlock_irqrestore(&l3_emif_lock, flags);
+
+ if (i == MAX_FREQ_UPDATE_TIMEOUT) {
+ pr_err("%s: Frequency update failed (call from %pF)\n",
+ __func__, (void *)_RET_IP_);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Use a very high retry count - we should not hit this condition */
+#define MAX_DPLL_WAIT_TRIES 1000000
+
+#define OMAP_1_5GHz 1500000000
+#define OMAP_1_2GHz 1200000000
+#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 +289,370 @@ const struct clkops clkops_omap4_dpllmx_ops = {
.deny_idle = omap4_dpllmx_deny_gatectrl,
};
+static void omap4460_mpu_dpll_update_children(unsigned long rate)
+{
+ u32 v;
+
+ /*
+ * 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);
+}
+
+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;
+
+ if (rate > clk->rate)
+ omap4460_mpu_dpll_update_children(rate);
+
+ /*
+ * 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);
+ if (rate <= OMAP_1_5GHz) {
+ /* If DCC is enabled, disable it */
+ v = __raw_readl(dd->mult_div1_reg);
+ if (v & OMAP4460_DCC_EN_MASK) {
+ v &= ~OMAP4460_DCC_EN_MASK;
+ __raw_writel(v, dd->mult_div1_reg);
+ }
+
+ if (rate != dpll_rate)
+ clk->parent->set_rate(clk->parent, rate);
+ } else {
+ /*
+ * 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.
+ */
+ if (rate != dpll_rate * 2)
+ clk->parent->set_rate(clk->parent, rate / 2);
+
+ v = __raw_readl(dd->mult_div1_reg);
+ v &= ~OMAP4460_DCC_COUNT_MAX_MASK;
+ v |= (5 << OMAP4460_DCC_COUNT_MAX_SHIFT);
+ __raw_writel(v, dd->mult_div1_reg);
+
+ v |= OMAP4460_DCC_EN_MASK;
+ __raw_writel(v, dd->mult_div1_reg);
+ }
+
+ if (rate < clk->rate)
+ omap4460_mpu_dpll_update_children(rate);
+
+ clk->rate = rate;
+
+ 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->parent, 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);
+}
+
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
+{
+ u32 v;
+ unsigned long rate;
+ struct dpll_data *dd;
+
+ if (!clk || !clk->dpll_data)
+ return -EINVAL;
+
+ dd = clk->dpll_data;
+
+ rate = omap2_get_dpll_rate(clk);
+
+ /* regm4xen adds a multiplier of 4 to DPLL calculations */
+ v = __raw_readl(dd->control_reg);
+ if (v & OMAP4430_DPLL_REGM4XEN_MASK)
+ rate *= OMAP4430_REGM4XEN_MULT;
+
+ return rate;
+}
+
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
+{
+ u32 v;
+ struct dpll_data *dd;
+
+ if (!clk || !clk->dpll_data)
+ return -EINVAL;
+
+ dd = clk->dpll_data;
+
+ /* regm4xen adds a multiplier of 4 to DPLL calculations */
+ v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
+
+ if (v)
+ target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
+
+ omap2_dpll_round_rate(clk, target_rate);
+
+ if (v)
+ clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
+
+ return clk->dpll_data->last_rounded_rate;
+}
+
+struct dpll_reg_tuple {
+ u16 addr;
+ u32 val;
+};
+
+struct omap4_dpll_regs {
+ char *name;
+ u32 mod_partition;
+ u32 mod_inst;
+ struct dpll_reg_tuple clkmode;
+ struct dpll_reg_tuple autoidle;
+ struct dpll_reg_tuple idlest;
+ struct dpll_reg_tuple clksel;
+ struct dpll_reg_tuple div_m2;
+ struct dpll_reg_tuple div_m3;
+ struct dpll_reg_tuple div_m4;
+ struct dpll_reg_tuple div_m5;
+ struct dpll_reg_tuple div_m6;
+ struct dpll_reg_tuple div_m7;
+ struct dpll_reg_tuple clkdcoldo;
+};
+
+static struct omap4_dpll_regs dpll_regs[] = {
+ /* MPU DPLL */
+ { .name = "mpu",
+ .mod_partition = OMAP4430_CM1_PARTITION,
+ .mod_inst = OMAP4430_CM1_CKGEN_INST,
+ .clkmode = {.addr = OMAP4_CM_CLKMODE_DPLL_MPU_OFFSET},
+ .autoidle = {.addr = OMAP4_CM_AUTOIDLE_DPLL_MPU_OFFSET},
+ .idlest = {.addr = OMAP4_CM_IDLEST_DPLL_MPU_OFFSET},
+ .clksel = {.addr = OMAP4_CM_CLKSEL_DPLL_MPU_OFFSET},
+ .div_m2 = {.addr = OMAP4_CM_DIV_M2_DPLL_MPU_OFFSET},
+ },
+ /* IVA DPLL */
+ { .name = "iva",
+ .mod_partition = OMAP4430_CM1_PARTITION,
+ .mod_inst = OMAP4430_CM1_CKGEN_INST,
+ .clkmode = {.addr = OMAP4_CM_CLKMODE_DPLL_IVA_OFFSET},
+ .autoidle = {.addr = OMAP4_CM_AUTOIDLE_DPLL_IVA_OFFSET},
+ .idlest = {.addr = OMAP4_CM_IDLEST_DPLL_IVA_OFFSET},
+ .clksel = {.addr = OMAP4_CM_CLKSEL_DPLL_IVA_OFFSET},
+ .div_m4 = {.addr = OMAP4_CM_DIV_M4_DPLL_IVA_OFFSET},
+ .div_m5 = {.addr = OMAP4_CM_DIV_M5_DPLL_IVA_OFFSET},
+ },
+ /* ABE DPLL */
+ { .name = "abe",
+ .mod_partition = OMAP4430_CM1_PARTITION,
+ .mod_inst = OMAP4430_CM1_CKGEN_INST,
+ .clkmode = {.addr = OMAP4_CM_CLKMODE_DPLL_ABE_OFFSET},
+ .autoidle = {.addr = OMAP4_CM_AUTOIDLE_DPLL_ABE_OFFSET},
+ .idlest = {.addr = OMAP4_CM_IDLEST_DPLL_ABE_OFFSET},
+ .clksel = {.addr = OMAP4_CM_CLKSEL_DPLL_ABE_OFFSET},
+ .div_m2 = {.addr = OMAP4_CM_DIV_M2_DPLL_ABE_OFFSET},
+ .div_m3 = {.addr = OMAP4_CM_DIV_M3_DPLL_ABE_OFFSET},
+ },
+ /* USB DPLL */
+ { .name = "usb",
+ .mod_partition = OMAP4430_CM2_PARTITION,
+ .mod_inst = OMAP4430_CM2_CKGEN_INST,
+ .clkmode = {.addr = OMAP4_CM_CLKMODE_DPLL_USB_OFFSET},
+ .autoidle = {.addr = OMAP4_CM_AUTOIDLE_DPLL_USB_OFFSET},
+ .idlest = {.addr = OMAP4_CM_IDLEST_DPLL_USB_OFFSET},
+ .clksel = {.addr = OMAP4_CM_CLKSEL_DPLL_USB_OFFSET},
+ .div_m2 = {.addr = OMAP4_CM_DIV_M2_DPLL_USB_OFFSET},
+ .clkdcoldo = {.addr = OMAP4_CM_CLKDCOLDO_DPLL_USB_OFFSET},
+ },
+ /* PER DPLL */
+ { .name = "per",
+ .mod_partition = OMAP4430_CM2_PARTITION,
+ .mod_inst = OMAP4430_CM2_CKGEN_INST,
+ .clkmode = {.addr = OMAP4_CM_CLKMODE_DPLL_PER_OFFSET},
+ .autoidle = {.addr = OMAP4_CM_AUTOIDLE_DPLL_PER_OFFSET},
+ .idlest = {.addr = OMAP4_CM_IDLEST_DPLL_PER_OFFSET},
+ .clksel = {.addr = OMAP4_CM_CLKSEL_DPLL_PER_OFFSET},
+ .div_m2 = {.addr = OMAP4_CM_DIV_M2_DPLL_PER_OFFSET},
+ .div_m3 = {.addr = OMAP4_CM_DIV_M3_DPLL_PER_OFFSET},
+ .div_m4 = {.addr = OMAP4_CM_DIV_M4_DPLL_PER_OFFSET},
+ .div_m5 = {.addr = OMAP4_CM_DIV_M5_DPLL_PER_OFFSET},
+ .div_m6 = {.addr = OMAP4_CM_DIV_M6_DPLL_PER_OFFSET},
+ .div_m7 = {.addr = OMAP4_CM_DIV_M7_DPLL_PER_OFFSET},
+ },
+};
+
+static inline void omap4_dpll_store_reg(struct omap4_dpll_regs *dpll_reg,
+ struct dpll_reg_tuple *tuple)
+{
+ if (tuple->addr)
+ tuple->val =
+ omap4_cminst_read_inst_reg(dpll_reg->mod_partition,
+ dpll_reg->mod_inst, tuple->addr);
+}
+
+void omap4_dpll_prepare_off(void)
+{
+ u32 i;
+ struct omap4_dpll_regs *dpll_reg = dpll_regs;
+
+ for (i = 0; i < ARRAY_SIZE(dpll_regs); i++, dpll_reg++) {
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->clkmode);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->autoidle);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->clksel);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->div_m2);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->div_m3);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->div_m4);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->div_m5);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->div_m6);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->div_m7);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->clkdcoldo);
+ omap4_dpll_store_reg(dpll_reg, &dpll_reg->idlest);
+ }
+}
+
+static void omap4_dpll_print_reg(struct omap4_dpll_regs *dpll_reg, char *name,
+ struct dpll_reg_tuple *tuple)
+{
+ if (tuple->addr)
+ pr_warn("%s - Address offset = 0x%08x, value=0x%08x\n", name,
+ tuple->addr, tuple->val);
+}
+
+static void omap4_dpll_dump_regs(struct omap4_dpll_regs *dpll_reg)
+{
+ pr_warn("%s: Unable to lock dpll %s[part=%x inst=%x]:\n",
+ __func__, dpll_reg->name, dpll_reg->mod_partition,
+ dpll_reg->mod_inst);
+ omap4_dpll_print_reg(dpll_reg, "clksel", &dpll_reg->clksel);
+ omap4_dpll_print_reg(dpll_reg, "div_m2", &dpll_reg->div_m2);
+ omap4_dpll_print_reg(dpll_reg, "div_m3", &dpll_reg->div_m3);
+ omap4_dpll_print_reg(dpll_reg, "div_m4", &dpll_reg->div_m4);
+ omap4_dpll_print_reg(dpll_reg, "div_m5", &dpll_reg->div_m5);
+ omap4_dpll_print_reg(dpll_reg, "div_m6", &dpll_reg->div_m6);
+ omap4_dpll_print_reg(dpll_reg, "div_m7", &dpll_reg->div_m7);
+ omap4_dpll_print_reg(dpll_reg, "clkdcoldo", &dpll_reg->clkdcoldo);
+ omap4_dpll_print_reg(dpll_reg, "clkmode", &dpll_reg->clkmode);
+ omap4_dpll_print_reg(dpll_reg, "autoidle", &dpll_reg->autoidle);
+ if (dpll_reg->idlest.addr)
+ pr_warn("idlest - Address offset = 0x%08x, before val=0x%08x"
+ " after = 0x%08x\n", dpll_reg->idlest.addr,
+ dpll_reg->idlest.val,
+ omap4_cminst_read_inst_reg(dpll_reg->mod_partition,
+ dpll_reg->mod_inst,
+ dpll_reg->idlest.addr));
+}
+
+static void omap4_wait_dpll_lock(struct omap4_dpll_regs *dpll_reg)
+{
+ int j = 0;
+
+ /* Return if we dont need to lock. */
+ if ((dpll_reg->clkmode.val & OMAP4430_DPLL_EN_MASK) !=
+ DPLL_LOCKED << OMAP4430_DPLL_EN_SHIFT);
+ return;
+
+ while ((omap4_cminst_read_inst_reg(dpll_reg->mod_partition,
+ dpll_reg->mod_inst,
+ dpll_reg->idlest.addr)
+ & OMAP4430_ST_DPLL_CLK_MASK) !=
+ 0x1 << OMAP4430_ST_DPLL_CLK_SHIFT
+ && j < MAX_DPLL_WAIT_TRIES) {
+ j++;
+ udelay(1);
+ }
+
+ /* if we are unable to lock, warn and move on.. */
+ if (j == MAX_DPLL_WAIT_TRIES)
+ omap4_dpll_dump_regs(dpll_reg);
+}
+
+static inline void omap4_dpll_restore_reg(struct omap4_dpll_regs *dpll_reg,
+ struct dpll_reg_tuple *tuple)
+{
+ if (tuple->addr)
+ omap4_cminst_write_inst_reg(tuple->val, dpll_reg->mod_partition,
+ dpll_reg->mod_inst, tuple->addr);
+}
+
+void omap4_dpll_resume_off(void)
+{
+ u32 i;
+ struct omap4_dpll_regs *dpll_reg = dpll_regs;
+
+ for (i = 0; i < ARRAY_SIZE(dpll_regs); i++, dpll_reg++) {
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->clksel);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->div_m2);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->div_m3);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->div_m4);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->div_m5);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->div_m6);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->div_m7);
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->clkdcoldo);
+
+ /* Restore clkmode after the above registers are restored */
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->clkmode);
+
+ omap4_wait_dpll_lock(dpll_reg);
+
+ /* Restore autoidle settings after the dpll is locked */
+ omap4_dpll_restore_reg(dpll_reg, &dpll_reg->autoidle);
+ }
+}
diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c
new file mode 100644
index 0000000..e00032b
--- /dev/null
+++ b/arch/arm/mach-omap2/dvfs.c
@@ -0,0 +1,1314 @@
+/*
+ * 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 <linux/debugfs.h>
+#include <linux/seq_file.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"
+#include "pm.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 the 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 and also adds corresponding frequency
+ * request for that voltage. 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. This will take care of scaling domain's voltage
+ * and frequency together.
+ *
+ *
+ * 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);
+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 return the max available OPP.
+ * 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)) {
+ /*
+ * if there is no OPP for corresponding volt
+ * then return max available instead
+ */
+ opp = opp_find_freq_floor(dev, &f);
+ 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;
+ struct device *target_dev;
+ struct omap_vdd_dvfs_info *tdvfs_info;
+ struct opp *opp;
+ int i, ret;
+ unsigned long dep_volt = 0, new_freq = 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*/
+ ret = _add_vdd_user(_voltdm_to_dvfs_info(dep_info->_dep_voltdm),
+ dev, dep_volt);
+ if (ret)
+ dev_err(dev, "%s: Failed to add dep to domain %s volt=%ld\n",
+ __func__, dep_info->name, dep_volt);
+
+ /* And also add corresponding freq request */
+ tdvfs_info = _voltdm_to_dvfs_info(dep_info->_dep_voltdm);
+ if (!tdvfs_info) {
+ dev_warn(dev, "%s: no dvfs_info\n",
+ __func__);
+ return -ENODEV;
+ }
+ target_dev = _dvfs_info_to_dev(tdvfs_info);
+ if (!target_dev) {
+ dev_warn(dev, "%s: no target_dev\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ rcu_read_lock();
+ opp = _volt_to_opp(target_dev, dep_volt);
+ if (!IS_ERR(opp))
+ new_freq = opp_get_freq(opp);
+ rcu_read_unlock();
+
+ if (new_freq) {
+ ret = _add_freq_request(tdvfs_info, dev, target_dev, new_freq);
+ if (ret) {
+ dev_err(target_dev, "%s: freqadd(%s) failed %d[f=%ld,"
+ "v=%ld]\n", __func__, dev_name(dev),
+ i, new_freq, dep_volt);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * _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;
+ struct omap_volt_data *new_vdata;
+ struct omap_volt_data *curr_vdata;
+
+ 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;
+
+ new_vdata = omap_voltage_get_voltdata(voltdm, new_volt);
+ if (IS_ERR_OR_NULL(new_vdata)) {
+ pr_err("%s:%s: Bad New voltage data for %ld\n",
+ __func__, voltdm->name, new_volt);
+ return PTR_ERR(new_vdata);
+ }
+ new_volt = omap_get_operation_voltage(new_vdata);
+ curr_vdata = omap_voltage_get_curr_vdata(voltdm);
+ if (IS_ERR_OR_NULL(curr_vdata)) {
+ pr_err("%s:%s: Bad Current voltage data\n",
+ __func__, voltdm->name);
+ return PTR_ERR(curr_vdata);
+ }
+
+ /* Disable smartreflex module across voltage and frequency scaling */
+ omap_sr_disable(voltdm);
+
+ /* Pick up the current voltage ONLY after ensuring no changes occur */
+ curr_volt = omap_vp_get_curr_volt(voltdm);
+ if (!curr_volt)
+ curr_volt = omap_get_operation_voltage(curr_vdata);
+
+ /* Make a decision to scale dependent domain based on nominal voltage */
+ if (omap_get_nominal_voltage(new_vdata) >
+ omap_get_nominal_voltage(curr_vdata)) {
+ 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;
+ }
+ }
+
+ if (voltdm->abb && omap_get_nominal_voltage(new_vdata) >
+ omap_get_nominal_voltage(curr_vdata)) {
+ ret = omap_ldo_abb_pre_scale(voltdm, new_vdata);
+ if (ret) {
+ pr_err("%s: ABB prescale failed for vdd%s: %d\n",
+ __func__, voltdm->name, ret);
+ goto fail;
+ }
+ }
+
+ /* Now decide on switching OPP */
+ if (curr_volt == new_volt) {
+ volt_scale_dir = DVFS_VOLT_SCALE_NONE;
+ } else if (curr_volt < new_volt) {
+ ret = voltdm_scale(voltdm, new_vdata);
+ if (ret) {
+ dev_err(target_dev,
+ "%s: Unable to scale the %s to %ld volt\n",
+ __func__, voltdm->name, new_volt);
+ goto fail;
+ }
+ volt_scale_dir = DVFS_VOLT_SCALE_UP;
+ }
+
+ if (voltdm->abb && omap_get_nominal_voltage(new_vdata) >
+ omap_get_nominal_voltage(curr_vdata)) {
+ ret = omap_ldo_abb_post_scale(voltdm, new_vdata);
+ if (ret) {
+ pr_err("%s: ABB prescale failed for vdd%s: %d\n",
+ __func__, voltdm->name, ret);
+ 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 {
+ /*
+ * Is the dev of dep domain target_device?
+ * we'd probably have a voltage request without
+ * a frequency dependency, scale appropriate frequency
+ * if there are none pending
+ */
+ if (target_dev == dev) {
+ 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 (voltdm->abb && omap_get_nominal_voltage(new_vdata) <
+ omap_get_nominal_voltage(curr_vdata)) {
+ ret = omap_ldo_abb_pre_scale(voltdm, new_vdata);
+ if (ret) {
+ pr_err("%s: ABB prescale failed for vdd%s: %d\n",
+ __func__, voltdm->name, ret);
+ goto fail;
+ }
+ }
+
+ if (DVFS_VOLT_SCALE_DOWN == volt_scale_dir)
+ voltdm_scale(voltdm, new_vdata);
+
+ if (voltdm->abb && omap_get_nominal_voltage(new_vdata) <
+ omap_get_nominal_voltage(curr_vdata)) {
+ ret = omap_ldo_abb_post_scale(voltdm, new_vdata);
+ if (ret)
+ pr_err("%s: ABB postscale failed for vdd%s: %d\n",
+ __func__, voltdm->name, ret);
+ }
+
+ /* Make a decision to scale dependent domain based on nominal voltage */
+ if (omap_get_nominal_voltage(new_vdata) <
+ omap_get_nominal_voltage(curr_vdata)) {
+ _dep_scale_domains(target_dev, vdd);
+ }
+
+ /* Ensure that current voltage data pointer points to new volt */
+ if (curr_volt == new_volt && omap_get_nominal_voltage(new_vdata) !=
+ omap_get_nominal_voltage(curr_vdata)) {
+ voltdm->curr_volt = new_vdata;
+ omap_vp_update_errorgain(voltdm, new_vdata);
+ }
+
+ /* 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, new_vdata);
+
+ 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, new_freq = 0;
+ struct omap_vdd_dvfs_info *tdvfs_info;
+ struct platform_device *pdev;
+ struct omap_device *od;
+ struct device *dev;
+ 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;
+ }
+
+ if (!omap_pm_is_ready()) {
+ dev_dbg(target_dev, "%s: pm is not ready yet\n", __func__);
+ return -EBUSY;
+ }
+
+ /* 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 we dont find a max, try a floor at least */
+ if (IS_ERR(opp))
+ opp = opp_find_freq_floor(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;
+ }
+
+ /* Check for any dep domains and add the user request */
+ ret = _dep_scan_domains(target_dev, tdvfs_info->voltdm->vdd, volt);
+ if (ret) {
+ dev_err(target_dev,
+ "%s: Error in scan domains for vdd_%s\n",
+ __func__, tdvfs_info->voltdm->name);
+ goto out;
+ }
+
+ dev = _dvfs_info_to_dev(tdvfs_info);
+ if (!dev) {
+ dev_warn(dev, "%s: no target_dev\n",
+ __func__);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (dev != target_dev) {
+ rcu_read_lock();
+ opp = _volt_to_opp(dev, volt);
+ if (!IS_ERR(opp))
+ new_freq = opp_get_freq(opp);
+ rcu_read_unlock();
+ if (new_freq) {
+ ret = _add_freq_request(tdvfs_info, req_dev, dev,
+ new_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;
+ }
+ }
+ }
+
+ /* 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);
+
+#ifdef CONFIG_PM_DEBUG
+static int dvfs_dump_vdd(struct seq_file *sf, void *unused)
+{
+ int k;
+ struct omap_vdd_dvfs_info *dvfs_info;
+ struct omap_vdd_dev_list *tdev;
+ struct omap_dev_user_list *duser;
+ struct omap_vdd_user_list *vuser;
+ struct omap_vdd_info *vdd;
+ struct omap_vdd_dep_info *dep_info;
+ struct voltagedomain *voltdm;
+ struct omap_volt_data *volt_data;
+ int anyreq;
+ int anyreq2;
+
+ dvfs_info = (struct omap_vdd_dvfs_info *)sf->private;
+ if (IS_ERR_OR_NULL(dvfs_info)) {
+ pr_err("%s: NO DVFS?\n", __func__);
+ return -EINVAL;
+ }
+
+ voltdm = dvfs_info->voltdm;
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_err("%s: NO voltdm?\n", __func__);
+ return -EINVAL;
+ }
+
+ vdd = voltdm->vdd;
+ if (IS_ERR_OR_NULL(vdd)) {
+ pr_err("%s: NO vdd data?\n", __func__);
+ return -EINVAL;
+ }
+
+ seq_printf(sf, "vdd_%s\n", voltdm->name);
+ mutex_lock(&omap_dvfs_lock);
+ spin_lock(&dvfs_info->user_lock);
+
+ seq_printf(sf, "|- voltage requests\n| |\n");
+ anyreq = 0;
+ plist_for_each_entry(vuser, &dvfs_info->vdd_user_list, node) {
+ seq_printf(sf, "| |-%d: %s:%s\n",
+ vuser->node.prio,
+ dev_driver_string(vuser->dev), dev_name(vuser->dev));
+ anyreq = 1;
+ }
+
+ spin_unlock(&dvfs_info->user_lock);
+
+ if (!anyreq)
+ seq_printf(sf, "| `-none\n");
+ else
+ seq_printf(sf, "| X\n");
+ seq_printf(sf, "|\n");
+
+ seq_printf(sf, "|- frequency requests\n| |\n");
+ anyreq2 = 0;
+ list_for_each_entry(tdev, &dvfs_info->dev_list, node) {
+ anyreq = 0;
+ seq_printf(sf, "| |- %s:%s\n",
+ dev_driver_string(tdev->dev), dev_name(tdev->dev));
+ spin_lock(&tdev->user_lock);
+ plist_for_each_entry(duser, &tdev->freq_user_list, node) {
+ seq_printf(sf, "| | |-%d: %s:%s\n",
+ duser->node.prio,
+ dev_driver_string(duser->dev),
+ dev_name(duser->dev));
+ anyreq = 1;
+ }
+
+ spin_unlock(&tdev->user_lock);
+
+ if (!anyreq)
+ seq_printf(sf, "| | `-none\n");
+ else
+ seq_printf(sf, "| | X\n");
+ anyreq2 = 1;
+ }
+ if (!anyreq2)
+ seq_printf(sf, "| `-none\n");
+ else
+ seq_printf(sf, "| X\n");
+
+ volt_data = vdd->volt_data;
+ seq_printf(sf, "|- Supported voltages\n| |\n");
+ anyreq = 0;
+ while (volt_data && volt_data->volt_nominal) {
+ seq_printf(sf, "| |-%d\n", volt_data->volt_nominal);
+ anyreq = 1;
+ volt_data++;
+ }
+ if (!anyreq)
+ seq_printf(sf, "| `-none\n");
+ else
+ seq_printf(sf, "| X\n");
+
+ dep_info = vdd->dep_vdd_info;
+ seq_printf(sf, "`- voltage dependencies\n |\n");
+ anyreq = 0;
+ while (dep_info && dep_info->nr_dep_entries) {
+ struct omap_vdd_dep_volt *dep_table = dep_info->dep_table;
+
+ seq_printf(sf, " |-on vdd_%s\n", dep_info->name);
+
+ for (k = 0; k < dep_info->nr_dep_entries; k++) {
+ seq_printf(sf, " | |- %d => %d\n",
+ dep_table[k].main_vdd_volt,
+ dep_table[k].dep_vdd_volt);
+ }
+
+ anyreq = 1;
+ dep_info++;
+ }
+
+ if (!anyreq)
+ seq_printf(sf, " `- none\n");
+ else
+ seq_printf(sf, " X X\n");
+
+ mutex_unlock(&omap_dvfs_lock);
+ return 0;
+}
+
+static int dvfs_dbg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dvfs_dump_vdd, inode->i_private);
+}
+
+static struct file_operations debugdvfs_fops = {
+ .open = dvfs_dbg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry __initdata *dvfsdebugfs_dir;
+
+static void __init dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info)
+{
+ struct dentry *ddir;
+
+ /* create a base dir */
+ if (!dvfsdebugfs_dir)
+ dvfsdebugfs_dir = debugfs_create_dir("dvfs", NULL);
+ if (IS_ERR_OR_NULL(dvfsdebugfs_dir)) {
+ WARN_ONCE("%s: Unable to create base DVFS dir\n", __func__);
+ return;
+ }
+
+ if (IS_ERR_OR_NULL(dvfs_info->voltdm)) {
+ pr_err("%s: no voltdm\n", __func__);
+ return;
+ }
+
+ ddir = debugfs_create_dir(dvfs_info->voltdm->name, dvfsdebugfs_dir);
+ if (IS_ERR_OR_NULL(ddir)) {
+ pr_warning("%s: unable to create subdir %s\n", __func__,
+ dvfs_info->voltdm->name);
+ return;
+ }
+
+ debugfs_create_file("info", S_IRUGO, ddir,
+ (void *)dvfs_info, &debugdvfs_fops);
+}
+#else /* CONFIG_PM_DEBUG */
+static inline void dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info)
+{
+ return;
+}
+#endif /* CONFIG_PM_DEBUG */
+
+/**
+ * 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);
+ /* Init the device list */
+ INIT_LIST_HEAD(&dvfs_info->dev_list);
+
+ list_add(&dvfs_info->node, &omap_dvfs_info_list);
+
+ dvfs_dbg_init(dvfs_info);
+ }
+
+ /* 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->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..b0a0cd6
--- /dev/null
+++ b/arch/arm/mach-omap2/dvfs.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+#include <linux/mutex.h>
+extern struct mutex omap_dvfs_lock;
+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);
+
+static inline bool omap_dvfs_is_any_dev_scaling(void)
+{
+ return mutex_is_locked(&omap_dvfs_lock);
+}
+#else
+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;
+}
+static inline bool omap_dvfs_is_any_dev_scaling(void)
+{
+ return false;
+}
+#endif
+#endif
diff --git a/arch/arm/mach-omap2/emif.c b/arch/arm/mach-omap2/emif.c
new file mode 100644
index 0000000..8f4ec5f
--- /dev/null
+++ b/arch/arm/mach-omap2/emif.c
@@ -0,0 +1,1514 @@
+/*
+ * OMAP4 EMIF platform driver
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Aneesh V <aneesh@ti.com>
+ * Vibhore Vardhan <vvardhan@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/init.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <mach/emif-44xx.h>
+#include <mach/emif.h>
+#include <mach/lpddr2-jedec.h>
+#include <mach/omap4-common.h>
+
+#include "voltage.h"
+
+/* Utility macro for masking and setting a field in a register/variable */
+#define mask_n_set(reg, shift, msk, val) \
+ (reg) = (((reg) & ~(msk))|(((val) << (shift)) & msk))
+
+struct emif_instance {
+ void __iomem *base;
+ u16 irq;
+ struct platform_device *pdev;
+ bool ddr_refresh_disabled;
+};
+static struct emif_instance emif[EMIF_NUM_INSTANCES];
+static struct emif_regs *emif_curr_regs[EMIF_NUM_INSTANCES];
+static struct emif_regs *emif1_regs_cache[EMIF_MAX_NUM_FREQUENCIES];
+static struct emif_regs *emif2_regs_cache[EMIF_MAX_NUM_FREQUENCIES];
+static struct emif_device_details *emif_devices[2];
+static u32 emif_temperature_level[EMIF_NUM_INSTANCES] = { SDRAM_TEMP_NOMINAL,
+ SDRAM_TEMP_NOMINAL
+};
+
+static u32 emif_notify_pending;
+static u32 emif_thermal_handling_pending;
+static u32 T_den, T_num;
+
+static struct omap_device_pm_latency omap_emif_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+static void do_cancel_out(u32 *num, u32 *den, u32 factor)
+{
+ while (1) {
+ if (((*num) / factor * factor == (*num)) &&
+ ((*den) / factor * factor == (*den))) {
+ (*num) /= factor;
+ (*den) /= factor;
+ } else
+ break;
+ }
+}
+
+static void cancel_out(u32 *num, u32 *den)
+{
+ do_cancel_out(num, den, 2);
+ do_cancel_out(num, den, 3);
+ do_cancel_out(num, den, 5);
+ do_cancel_out(num, den, 7);
+ do_cancel_out(num, den, 11);
+ do_cancel_out(num, den, 13);
+ do_cancel_out(num, den, 17);
+}
+
+/*
+ * Get the period in ns (in fraction form) for a given frequency:
+ * Getting it in fraction form is for better accuracy in integer arithmetics
+ * freq_hz - input: frequency in Hertz
+ * den_limit - input: upper limit for denominator. see the description of
+ * EMIF_PERIOD_DEN_LIMIT for more details
+ * period_den - output: pointer to denominator of period in ns
+ * period_num - output: pointer to numerator of period in ns
+ */
+static void get_period(u32 freq_hz, u32 den_limit, u32 *period_num,
+ u32 *period_den)
+{
+ *period_num = 1000000000; /* 10^9 to convert the period to 'ns' */
+ *period_den = freq_hz;
+ cancel_out(period_num, period_den);
+ /* make sure den <= den_limit at the cost of some accuracy */
+ while ((*period_den) > den_limit) {
+ *period_num /= 2;
+ *period_den /= 2;
+ }
+}
+
+/*
+ * Calculate the period of DDR clock from frequency value and set the
+ * denominator and numerator in global variables for easy access later
+ */
+static void set_ddr_clk_period(u32 freq)
+{
+ get_period(freq, EMIF_PERIOD_DEN_LIMIT, &T_num, &T_den);
+}
+
+/*
+ * Convert time in nano seconds to number of cycles of DDR clock
+ */
+static u32 ns_2_cycles(u32 ns)
+{
+ return ((ns * T_den) + T_num - 1) / T_num;
+}
+
+/*
+ * ns_2_cycles with the difference that the time passed is 2 times the actual
+ * value(to avoid fractions). The cycles returned is for the original value of
+ * the timing parameter
+ */
+static u32 ns_x2_2_cycles(u32 ns)
+{
+ return ((ns * T_den) + T_num * 2 - 1) / (T_num * 2);
+}
+
+/*
+ * Find addressing table index based on the device's type(S2 or S4) and
+ * density
+ */
+static s8 addressing_table_index(u8 type, u8 density, u8 width)
+{
+ u8 index;
+ if (unlikely((density > LPDDR2_DENSITY_8Gb) ||
+ (width == LPDDR2_IO_WIDTH_8)))
+ return -1;
+
+ /*
+ * Look at the way ADDR_TABLE_INDEX* values have been defined
+ * in emif.h compared to LPDDR2_DENSITY_* values
+ * The table is layed out in the increasing order of density
+ * (ignoring type). The exceptions 1GS2 and 2GS2 have been placed
+ * at the end
+ */
+ if ((type == LPDDR2_TYPE_S2) && (density == LPDDR2_DENSITY_1Gb))
+ index = ADDR_TABLE_INDEX1GS2;
+ else if ((type == LPDDR2_TYPE_S2) && (density == LPDDR2_DENSITY_2Gb))
+ index = ADDR_TABLE_INDEX2GS2;
+ else
+ index = density;
+
+ pr_debug("emif: addressing table index %d", index);
+
+ return index;
+}
+
+/*
+ * Find the the right timing table from the array of timing
+ * tables of the device using DDR clock frequency
+ */
+static const struct lpddr2_timings *get_timings_table(
+ const struct lpddr2_timings * const *device_timings, u32 freq)
+{
+ u32 i, temp, freq_nearest;
+ const struct lpddr2_timings *timings = NULL;
+
+ emif_assert(freq <= MAX_LPDDR2_FREQ);
+ emif_assert(device_timings);
+
+ /*
+ * Start with the maximum allowed frequency - that is always safe
+ */
+ freq_nearest = MAX_LPDDR2_FREQ;
+ /*
+ * Find the timings table that has the max frequency value:
+ * i. Above or equal to the DDR frequency - safe
+ * ii. The lowest that satisfies condition (i) - optimal
+ */
+ for (i = 0; i < MAX_NUM_SPEEDBINS; i++) {
+ if (device_timings[i]) {
+ temp = device_timings[i]->max_freq;
+ if ((temp >= freq) && (temp <= freq_nearest)) {
+ freq_nearest = temp;
+ timings = device_timings[i];
+ }
+ }
+ }
+ pr_debug("emif: timings table: %d", freq_nearest);
+ return timings;
+}
+
+/*
+ * Finds the value of emif_sdram_config_reg
+ * All parameters are programmed based on the device on CS0.
+ * If there is a device on CS1, it will be same as that on CS0 or
+ * it will be NVM. We don't support NVM yet.
+ * If cs1_device pointer is NULL it is assumed that there is no device
+ * on CS1
+ */
+static u32 get_sdram_config_reg(const struct lpddr2_device_info *cs0_device,
+ const struct lpddr2_device_info *cs1_device,
+ const struct lpddr2_addressing *addressing,
+ u8 RL)
+{
+ u32 config_reg = 0;
+
+ mask_n_set(config_reg, OMAP44XX_REG_SDRAM_TYPE_SHIFT,
+ OMAP44XX_REG_SDRAM_TYPE_MASK, cs0_device->type + 4);
+
+ mask_n_set(config_reg, OMAP44XX_REG_IBANK_POS_SHIFT,
+ OMAP44XX_REG_IBANK_POS_MASK,
+ EMIF_INTERLEAVING_POLICY_MAX_INTERLEAVING);
+
+ mask_n_set(config_reg, OMAP44XX_REG_NARROW_MODE_SHIFT,
+ OMAP44XX_REG_NARROW_MODE_MASK, cs0_device->io_width);
+
+ mask_n_set(config_reg, OMAP44XX_REG_CL_SHIFT, OMAP44XX_REG_CL_MASK, RL);
+
+ mask_n_set(config_reg, OMAP44XX_REG_ROWSIZE_SHIFT,
+ OMAP44XX_REG_ROWSIZE_MASK,
+ addressing->row_sz[cs0_device->io_width]);
+
+ mask_n_set(config_reg, OMAP44XX_REG_IBANK_SHIFT,
+ OMAP44XX_REG_IBANK_MASK, addressing->num_banks);
+
+ mask_n_set(config_reg, OMAP44XX_REG_EBANK_SHIFT,
+ OMAP44XX_REG_EBANK_MASK,
+ (cs1_device ? EBANK_CS1_EN : EBANK_CS1_DIS));
+
+ mask_n_set(config_reg, OMAP44XX_REG_PAGESIZE_SHIFT,
+ OMAP44XX_REG_PAGESIZE_MASK,
+ addressing->col_sz[cs0_device->io_width]);
+
+ return config_reg;
+}
+
+static u32 get_sdram_ref_ctrl(u32 freq,
+ const struct lpddr2_addressing *addressing)
+{
+ u32 ref_ctrl = 0, val = 0, freq_khz;
+ freq_khz = freq / 1000;
+ /*
+ * refresh rate to be set is 'tREFI * freq in MHz
+ * division by 10000 to account for khz and x10 in t_REFI_us_x10
+ */
+ val = addressing->t_REFI_us_x10 * freq_khz / 10000;
+ mask_n_set(ref_ctrl, OMAP44XX_REG_REFRESH_RATE_SHIFT,
+ OMAP44XX_REG_REFRESH_RATE_MASK, val);
+
+ /* enable refresh */
+ mask_n_set(ref_ctrl, OMAP44XX_REG_INITREF_DIS_SHIFT,
+ OMAP44XX_REG_INITREF_DIS_MASK, 1);
+ return ref_ctrl;
+}
+
+static u32 get_sdram_tim_1_reg(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing *addressing)
+{
+ u32 tim1 = 0, val = 0;
+ val = max(min_tck->tWTR, ns_x2_2_cycles(timings->tWTRx2)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_WTR_SHIFT, OMAP44XX_REG_T_WTR_MASK,
+ val);
+
+ if (addressing->num_banks == BANKS8)
+ val = (timings->tFAW * T_den + 4 * T_num - 1) / (4 * T_num) - 1;
+ else
+ val = max(min_tck->tRRD, ns_2_cycles(timings->tRRD)) - 1;
+
+ mask_n_set(tim1, OMAP44XX_REG_T_RRD_SHIFT, OMAP44XX_REG_T_RRD_MASK,
+ val);
+
+ val = ns_2_cycles(timings->tRASmin + timings->tRPab) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RC_SHIFT, OMAP44XX_REG_T_RC_MASK, val);
+
+ val = max(min_tck->tRAS_MIN, ns_2_cycles(timings->tRASmin)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RAS_SHIFT, OMAP44XX_REG_T_RAS_MASK,
+ val);
+
+ val = max(min_tck->tWR, ns_2_cycles(timings->tWR)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_WR_SHIFT, OMAP44XX_REG_T_WR_MASK, val);
+
+ val = max(min_tck->tRCD, ns_2_cycles(timings->tRCD)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RCD_SHIFT, OMAP44XX_REG_T_RCD_MASK,
+ val);
+ val = max(min_tck->tRP_AB, ns_2_cycles(timings->tRPab)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RP_SHIFT, OMAP44XX_REG_T_RP_MASK, val);
+
+ return tim1;
+}
+
+/*
+ * Finds the de-rated value for EMIF_SDRAM_TIM1 register
+ * All the de-rated timings are limited to this register
+ * Adds 2ns instead of 1.875ns to the affected timings as
+ * we can not use float.
+ */
+static u32 get_sdram_tim_1_reg_derated(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing
+ *addressing)
+{
+ u32 tim1 = 0, val = 0;
+ val = max(min_tck->tWTR, ns_x2_2_cycles(timings->tWTRx2)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_WTR_SHIFT, OMAP44XX_REG_T_WTR_MASK,
+ val);
+
+ if (addressing->num_banks == BANKS8)
+ /*
+ * tFAW is approximately 4 times tRRD. So add 1.875*4 = 7.5 ~ 8
+ * to tFAW for de-rating
+ */
+ val = ((timings->tFAW + 8) * T_den + 4 * T_num - 1)
+ / (4 * T_num) - 1;
+ else
+ val = max(min_tck->tRRD, ns_2_cycles(timings->tRRD + 2)) - 1;
+
+ mask_n_set(tim1, OMAP44XX_REG_T_RRD_SHIFT, OMAP44XX_REG_T_RRD_MASK,
+ val);
+
+ val = ns_2_cycles(timings->tRASmin + timings->tRPab + 2) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RC_SHIFT, OMAP44XX_REG_T_RC_MASK, val);
+
+ val = max(min_tck->tRAS_MIN, ns_2_cycles(timings->tRASmin + 2)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RAS_SHIFT, OMAP44XX_REG_T_RAS_MASK,
+ val);
+
+ val = max(min_tck->tWR, ns_2_cycles(timings->tWR)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_WR_SHIFT, OMAP44XX_REG_T_WR_MASK, val);
+
+ val = max(min_tck->tRCD, ns_2_cycles(timings->tRCD + 2)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RCD_SHIFT, OMAP44XX_REG_T_RCD_MASK,
+ val);
+ val = max(min_tck->tRP_AB, ns_2_cycles(timings->tRPab + 2)) - 1;
+ mask_n_set(tim1, OMAP44XX_REG_T_RP_SHIFT, OMAP44XX_REG_T_RP_MASK, val);
+
+ return tim1;
+}
+
+static u32 get_sdram_tim_2_reg(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck)
+{
+ u32 tim2 = 0, val = 0;
+ val = max(min_tck->tCKE, timings->tCKE) - 1;
+ mask_n_set(tim2, OMAP44XX_REG_T_CKE_SHIFT, OMAP44XX_REG_T_CKE_MASK,
+ val);
+
+ val = max(min_tck->tRTP, ns_x2_2_cycles(timings->tRTPx2)) - 1;
+ mask_n_set(tim2, OMAP44XX_REG_T_RTP_SHIFT, OMAP44XX_REG_T_RTP_MASK,
+ val);
+
+ /*
+ * tXSRD = tRFCab + 10 ns. XSRD and XSNR should have the
+ * same value
+ */
+ val = ns_2_cycles(timings->tXSR) - 1;
+ mask_n_set(tim2, OMAP44XX_REG_T_XSRD_SHIFT, OMAP44XX_REG_T_XSRD_MASK,
+ val);
+ mask_n_set(tim2, OMAP44XX_REG_T_XSNR_SHIFT, OMAP44XX_REG_T_XSNR_MASK,
+ val);
+
+ val = max(min_tck->tXP, ns_x2_2_cycles(timings->tXPx2)) - 1;
+ mask_n_set(tim2, OMAP44XX_REG_T_XP_SHIFT, OMAP44XX_REG_T_XP_MASK, val);
+
+ return tim2;
+}
+
+static u32 get_sdram_tim_3_reg(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing *addressing)
+{
+ u32 tim3 = 0, val = 0;
+ val = min(timings->tRASmax * 10 / addressing->t_REFI_us_x10 - 1, 0xF);
+ mask_n_set(tim3, OMAP44XX_REG_T_RAS_MAX_SHIFT,
+ OMAP44XX_REG_T_RAS_MAX_MASK, val);
+
+ val = ns_2_cycles(timings->tRFCab) - 1;
+ mask_n_set(tim3, OMAP44XX_REG_T_RFC_SHIFT, OMAP44XX_REG_T_RFC_MASK,
+ val);
+
+ val = ns_x2_2_cycles(timings->tDQSCKMAXx2) - 1;
+ mask_n_set(tim3, OMAP44XX_REG_T_TDQSCKMAX_SHIFT,
+ OMAP44XX_REG_T_TDQSCKMAX_MASK, val);
+
+ val = ns_2_cycles(timings->tZQCS) - 1;
+ mask_n_set(tim3, OMAP44XX_REG_ZQ_ZQCS_SHIFT,
+ OMAP44XX_REG_ZQ_ZQCS_MASK, val);
+
+ val = max(min_tck->tCKESR, ns_2_cycles(timings->tCKESR)) - 1;
+ mask_n_set(tim3, OMAP44XX_REG_T_CKESR_SHIFT,
+ OMAP44XX_REG_T_CKESR_MASK, val);
+
+ return tim3;
+}
+
+static u32 get_zq_config_reg(const struct lpddr2_device_info *cs1_device,
+ const struct lpddr2_addressing *addressing,
+ bool volt_ramp)
+{
+ u32 zq = 0, val = 0;
+ if (volt_ramp)
+ val =
+ EMIF_ZQCS_INTERVAL_DVFS_IN_US * 10 /
+ addressing->t_REFI_us_x10;
+ else
+ val =
+ EMIF_ZQCS_INTERVAL_NORMAL_IN_US * 10 /
+ addressing->t_REFI_us_x10;
+ mask_n_set(zq, OMAP44XX_REG_ZQ_REFINTERVAL_SHIFT,
+ OMAP44XX_REG_ZQ_REFINTERVAL_MASK, val);
+
+ mask_n_set(zq, OMAP44XX_REG_ZQ_ZQCL_MULT_SHIFT,
+ OMAP44XX_REG_ZQ_ZQCL_MULT_MASK, REG_ZQ_ZQCL_MULT - 1);
+
+ mask_n_set(zq, OMAP44XX_REG_ZQ_ZQINIT_MULT_SHIFT,
+ OMAP44XX_REG_ZQ_ZQINIT_MULT_MASK, REG_ZQ_ZQINIT_MULT - 1);
+
+ mask_n_set(zq, OMAP44XX_REG_ZQ_SFEXITEN_SHIFT,
+ OMAP44XX_REG_ZQ_SFEXITEN_MASK, REG_ZQ_SFEXITEN_ENABLE);
+
+ /*
+ * Assuming that two chipselects have a single calibration resistor
+ * If there are indeed two calibration resistors, then this flag should
+ * be enabled to take advantage of dual calibration feature.
+ * This data should ideally come from board files. But considering
+ * that none of the boards today have calibration resistors per CS,
+ * it would be an unnecessary overhead.
+ */
+ mask_n_set(zq, OMAP44XX_REG_ZQ_DUALCALEN_SHIFT,
+ OMAP44XX_REG_ZQ_DUALCALEN_MASK, REG_ZQ_DUALCALEN_DISABLE);
+
+ mask_n_set(zq, OMAP44XX_REG_ZQ_CS0EN_SHIFT,
+ OMAP44XX_REG_ZQ_CS0EN_MASK, REG_ZQ_CS0EN_ENABLE);
+
+ mask_n_set(zq, OMAP44XX_REG_ZQ_CS1EN_SHIFT,
+ OMAP44XX_REG_ZQ_CS1EN_MASK, (cs1_device ? 1 : 0));
+
+ return zq;
+}
+
+static u32 get_temp_alert_config(const struct lpddr2_device_info *cs1_device,
+ const struct lpddr2_addressing *addressing,
+ bool is_derated)
+{
+ u32 alert = 0, interval;
+ interval =
+ TEMP_ALERT_POLL_INTERVAL_MS * 10000 / addressing->t_REFI_us_x10;
+ if (is_derated)
+ interval *= 4;
+ mask_n_set(alert, OMAP44XX_REG_TA_REFINTERVAL_SHIFT,
+ OMAP44XX_REG_TA_REFINTERVAL_MASK, interval);
+
+ mask_n_set(alert, OMAP44XX_REG_TA_DEVCNT_SHIFT,
+ OMAP44XX_REG_TA_DEVCNT_MASK, TEMP_ALERT_CONFIG_DEVCT_1);
+
+ mask_n_set(alert, OMAP44XX_REG_TA_DEVWDT_SHIFT,
+ OMAP44XX_REG_TA_DEVWDT_MASK, TEMP_ALERT_CONFIG_DEVWDT_32);
+
+ mask_n_set(alert, OMAP44XX_REG_TA_SFEXITEN_SHIFT,
+ OMAP44XX_REG_TA_SFEXITEN_MASK, 1);
+
+ mask_n_set(alert, OMAP44XX_REG_TA_CS0EN_SHIFT,
+ OMAP44XX_REG_TA_CS0EN_MASK, 1);
+
+ mask_n_set(alert, OMAP44XX_REG_TA_CS1EN_SHIFT,
+ OMAP44XX_REG_TA_CS1EN_MASK, (cs1_device ? 1 : 0));
+
+ return alert;
+}
+
+static u32 get_read_idle_ctrl_reg(bool volt_ramp)
+{
+ u32 idle = 0, val = 0;
+ if (volt_ramp)
+ val = ns_2_cycles(READ_IDLE_INTERVAL_DVFS) / 64 - 1;
+ else
+ /*Maximum value in normal conditions - suggested by hw team */
+ val = 0x1FF;
+ mask_n_set(idle, OMAP44XX_REG_READ_IDLE_INTERVAL_SHIFT,
+ OMAP44XX_REG_READ_IDLE_INTERVAL_MASK, val);
+
+ mask_n_set(idle, OMAP44XX_REG_READ_IDLE_LEN_SHIFT,
+ OMAP44XX_REG_READ_IDLE_LEN_MASK, EMIF_REG_READ_IDLE_LEN_VAL);
+
+ return idle;
+}
+
+static u32 get_ddr_phy_ctrl_1(u32 freq, u8 RL)
+{
+ u32 phy = 0, val = 0;
+
+ mask_n_set(phy, OMAP44XX_REG_READ_LATENCY_SHIFT,
+ OMAP44XX_REG_READ_LATENCY_MASK, RL + 2);
+
+ if (freq <= 100000000)
+ val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS;
+ else if (freq <= 200000000)
+ val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ;
+ else
+ val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ;
+ mask_n_set(phy, OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_SHIFT,
+ OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_MASK, val);
+
+ /* Other fields are constant magic values. Hardcode them together */
+ mask_n_set(phy, OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_SHIFT,
+ OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_MASK,
+ EMIF_DDR_PHY_CTRL_1_BASE_VAL);
+
+ phy >>= OMAP44XX_REG_DDR_PHY_CTRL_1_SHIFT;
+
+ return phy;
+}
+
+/*
+ * get_lp_mode - Get the LP Mode of a EMIF instance.
+ *
+ * It returns the REG_LP_MODE of EMIF_PWR_MGMT_CTRL[10:8]
+ * for a EMIF.
+ *
+ */
+static u32 get_lp_mode(u32 emif_nr)
+{
+ u32 temp, lpmode;
+ void __iomem *base = emif[emif_nr].base;
+
+ temp = readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+ lpmode = (temp & OMAP44XX_REG_LP_MODE_MASK) >>
+ OMAP44XX_REG_LP_MODE_SHIFT;
+
+ return lpmode;
+}
+
+/*
+ * set_lp_mode - Set the LP Mode of a EMIF instance.
+ *
+ * It replaces the REG_LP_MODE of EMIF_PWR_MGMT_CTRL[10:8]
+ * with the new value for a EMIF.
+ *
+ */
+static void set_lp_mode(u32 emif_nr, u32 lpmode)
+{
+ u32 temp;
+ void __iomem *base = emif[emif_nr].base;
+
+ /* Extract current lp mode value */
+ temp = readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+
+ /* Write out the new lp mode value */
+ temp &= ~OMAP44XX_REG_LP_MODE_MASK;
+ temp |= lpmode << OMAP44XX_REG_LP_MODE_SHIFT;
+ writel(temp, base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+
+}
+
+/*
+ * Get the temperature level of the EMIF instance:
+ * Reads the MR4 register of attached SDRAM parts to find out the temperature
+ * level. If there are two parts attached(one on each CS), then the temperature
+ * level for the EMIF instance is the higher of the two temperatures.
+ */
+static u32 get_temperature_level(u32 emif_nr)
+{
+ u32 temp, tmp_temperature_level;
+ bool cs1_used;
+ void __iomem *base;
+
+ base = emif[emif_nr].base;
+
+ temp = __raw_readl(base + OMAP44XX_EMIF_SDRAM_CONFIG);
+ cs1_used = (temp & OMAP44XX_REG_EBANK_MASK) ? true : false;
+
+ /* Read mode register 4 */
+ __raw_writel(LPDDR2_MR4, base + OMAP44XX_EMIF_LPDDR2_MODE_REG_CFG);
+ tmp_temperature_level = __raw_readl(base +
+ OMAP44XX_EMIF_LPDDR2_MODE_REG_DATA);
+
+ tmp_temperature_level = (tmp_temperature_level &
+ MR4_SDRAM_REF_RATE_MASK) >>
+ MR4_SDRAM_REF_RATE_SHIFT;
+
+ if (cs1_used) {
+ __raw_writel(LPDDR2_MR4 | OMAP44XX_REG_CS_MASK,
+ base + OMAP44XX_EMIF_LPDDR2_MODE_REG_CFG);
+ temp = __raw_readl(base + OMAP44XX_EMIF_LPDDR2_MODE_REG_DATA);
+ temp = (temp & MR4_SDRAM_REF_RATE_MASK)
+ >> MR4_SDRAM_REF_RATE_SHIFT;
+ tmp_temperature_level = max(temp, tmp_temperature_level);
+ }
+
+ /* treat everything less than nominal(3) in MR4 as nominal */
+ if (unlikely(tmp_temperature_level < SDRAM_TEMP_NOMINAL))
+ tmp_temperature_level = SDRAM_TEMP_NOMINAL;
+
+ /* if we get reserved value in MR4 persist with the existing value */
+ if (unlikely(tmp_temperature_level == SDRAM_TEMP_RESERVED_4))
+ tmp_temperature_level = emif_temperature_level[emif_nr];
+
+ return tmp_temperature_level;
+}
+
+/*
+ * Program EMIF shadow registers:
+ * Sets the shadow registers using pre-caulated register values
+ * When volt_state indicates that this function is called just before
+ * a voltage scaling, set only the registers relevant for voltage scaling
+ * Otherwise, set all the registers relevant for a frequency change
+ */
+static void setup_registers(u32 emif_nr, struct emif_regs *regs, u32 volt_state)
+{
+ u32 temp,read_idle;
+ void __iomem *base = emif[emif_nr].base;
+
+ __raw_writel(regs->ref_ctrl, base + OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW);
+
+ __raw_writel(regs->sdram_tim2, base + OMAP44XX_EMIF_SDRAM_TIM_2_SHDW);
+ __raw_writel(regs->sdram_tim3, base + OMAP44XX_EMIF_SDRAM_TIM_3_SHDW);
+ /*
+ * Do not change the RL part in PHY CTRL register
+ * RL is not changed during DVFS
+ */
+ temp = __raw_readl(base + OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW);
+ mask_n_set(temp, OMAP44XX_REG_DDR_PHY_CTRL_1_SHDW_SHIFT,
+ OMAP44XX_REG_DDR_PHY_CTRL_1_SHDW_MASK,
+ regs->emif_ddr_phy_ctlr_1_final);
+ __raw_writel(temp, base + OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW);
+
+ __raw_writel(regs->temp_alert_config,
+ base + OMAP44XX_EMIF_TEMP_ALERT_CONFIG);
+
+ /*
+ * When voltage ramps forced read idle should
+ * happen more often.
+ */
+ if (volt_state == LPDDR2_VOLTAGE_RAMPING)
+ read_idle = regs->read_idle_ctrl_volt_ramp;
+ else
+ read_idle = regs->read_idle_ctrl_normal;
+ __raw_writel(read_idle, base + OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW);
+
+ /*
+ * Reading back the last written register to ensure all writes are
+ * complete
+ */
+ temp = __raw_readl(base + OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW);
+}
+
+/*
+ * setup_temperature_sensitive_regs() - set the timings for temperature
+ * sensitive registers. This happens once at initialization time based
+ * on the temperature at boot time and subsequently based on the temperature
+ * alert interrupt. Temperature alert can happen when the temperature
+ * increases or drops. So this function can have the effect of either
+ * derating the timings or going back to nominal values.
+ */
+static void setup_temperature_sensitive_regs(u32 emif_nr,
+ struct emif_regs *regs)
+{
+ u32 tim1, ref_ctrl, temp_alert_cfg;
+ void __iomem *base = emif[emif_nr].base;
+ u32 temperature = emif_temperature_level[emif_nr];
+
+ if (unlikely(temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH)) {
+ tim1 = regs->sdram_tim1;
+ ref_ctrl = regs->ref_ctrl_derated;
+ temp_alert_cfg = regs->temp_alert_config_derated;
+ } else if (unlikely(temperature ==
+ SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS)) {
+ tim1 = regs->sdram_tim1_derated;
+ ref_ctrl = regs->ref_ctrl_derated;
+ temp_alert_cfg = regs->temp_alert_config_derated;
+ } else {
+ /*
+ * Nominal timings - you may switch back to the
+ * nominal timings if the temperature falls
+ */
+ tim1 = regs->sdram_tim1;
+ ref_ctrl = regs->ref_ctrl;
+ temp_alert_cfg = regs->temp_alert_config;
+ }
+
+ __raw_writel(tim1, base + OMAP44XX_EMIF_SDRAM_TIM_1_SHDW);
+ __raw_writel(temp_alert_cfg, base + OMAP44XX_EMIF_TEMP_ALERT_CONFIG);
+ __raw_writel(ref_ctrl, base + OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW);
+
+ /* read back last written register to ensure write is complete */
+ __raw_readl(base + OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW);
+}
+
+static irqreturn_t handle_temp_alert(void __iomem *base, u32 emif_nr)
+{
+ u32 old_temperature_level;
+ old_temperature_level = emif_temperature_level[emif_nr];
+ emif_temperature_level[emif_nr] = get_temperature_level(emif_nr);
+
+ if (unlikely(emif_temperature_level[emif_nr] == old_temperature_level))
+ return IRQ_HANDLED;
+
+ emif_notify_pending |= (1 << emif_nr);
+ if (likely(emif_temperature_level[emif_nr] < old_temperature_level)) {
+ /* Temperature coming down - defer handling to thread */
+ emif_thermal_handling_pending |= (1 << emif_nr);
+ } else if (likely(emif_temperature_level[emif_nr] !=
+ SDRAM_TEMP_VERY_HIGH_SHUTDOWN)) {
+ /* Temperature is going up - handle immediately */
+ setup_temperature_sensitive_regs(emif_nr,
+ emif_curr_regs[emif_nr]);
+ /*
+ * EMIF de-rated timings register needs to be setup using
+ * freq update method only
+ */
+ omap4_prcm_freq_update();
+ }
+ return IRQ_WAKE_THREAD;
+}
+
+static void setup_volt_sensitive_registers(u32 emif_nr, struct emif_regs *regs,
+ u32 volt_state)
+{
+ u32 read_idle;
+ void __iomem *base = emif[emif_nr].base;
+ /*
+ * When voltage ramps forced read idle should
+ * happen more often.
+ */
+ if (volt_state == LPDDR2_VOLTAGE_RAMPING)
+ read_idle = regs->read_idle_ctrl_volt_ramp;
+ else
+ read_idle = regs->read_idle_ctrl_normal;
+
+ __raw_writel(read_idle, base + OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW);
+
+ /* read back last written register to ensure write is complete */
+ __raw_readl(base + OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW);
+
+ return;
+}
+
+/*
+ * Interrupt Handler for EMIF1 and EMIF2
+ */
+static irqreturn_t emif_interrupt_handler(int irq, void *dev_id)
+{
+ void __iomem *base;
+ irqreturn_t ret = IRQ_HANDLED;
+ u32 sys, ll;
+ u8 emif_nr = EMIF1;
+
+ if (emif[EMIF2].irq == irq)
+ emif_nr = EMIF2;
+
+ base = emif[emif_nr].base;
+
+ /* Save the status and clear it */
+ sys = __raw_readl(base + OMAP44XX_EMIF_IRQSTATUS_SYS);
+ ll = __raw_readl(base + OMAP44XX_EMIF_IRQSTATUS_LL);
+ __raw_writel(sys, base + OMAP44XX_EMIF_IRQSTATUS_SYS);
+ __raw_writel(ll, base + OMAP44XX_EMIF_IRQSTATUS_LL);
+ /*
+ * Handle temperature alert
+ * Temperature alert should be same for both ports
+ * So, it's enough to process it for only one of the ports
+ */
+ if (sys & OMAP44XX_REG_TA_SYS_MASK)
+ ret = handle_temp_alert(base, emif_nr);
+
+ if (sys & OMAP44XX_REG_ERR_SYS_MASK)
+ pr_err("EMIF: Access error from EMIF%d SYS port - %x",
+ emif_nr, sys);
+
+ if (ll & OMAP44XX_REG_ERR_LL_MASK)
+ pr_err("EMIF Error: Access error from EMIF%d LL port - %x",
+ emif_nr, ll);
+
+ return ret;
+}
+
+static irqreturn_t emif_threaded_isr(int irq, void *dev_id)
+{
+ u8 emif_nr = EMIF1;
+ if (emif[EMIF2].irq == irq)
+ emif_nr = EMIF2;
+
+ if (emif_thermal_handling_pending & (1 << emif_nr)) {
+ setup_temperature_sensitive_regs(emif_nr,
+ emif_curr_regs[emif_nr]);
+ /*
+ * EMIF de-rated timings register needs to be setup using
+ * freq update method only
+ */
+ omap4_prcm_freq_update();
+ /* clear the bit */
+ emif_thermal_handling_pending &= ~(1 << emif_nr);
+ }
+ if (emif_notify_pending & (1 << emif_nr)) {
+ sysfs_notify(&(emif[emif_nr].pdev->dev.kobj), NULL,
+ "temperature");
+ kobject_uevent(&(emif[emif_nr].pdev->dev.kobj), KOBJ_CHANGE);
+ /* clear the bit */
+ emif_notify_pending &= ~(1 << emif_nr);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __init setup_emif_interrupts(u32 emif_nr)
+{
+ u32 temp;
+ void __iomem *base = emif[emif_nr].base;
+ int r;
+
+ /* Clear any pendining interrupts */
+ __raw_writel(0xFFFFFFFF, base + OMAP44XX_EMIF_IRQSTATUS_SYS);
+ __raw_writel(0xFFFFFFFF, base + OMAP44XX_EMIF_IRQSTATUS_LL);
+
+ /* Enable the relevant interrupts for both LL and SYS */
+ temp = OMAP44XX_REG_EN_TA_SYS_MASK | OMAP44XX_REG_EN_ERR_SYS_MASK;
+ __raw_writel(temp, base + OMAP44XX_EMIF_IRQENABLE_SET_SYS);
+ __raw_writel(temp, base + OMAP44XX_EMIF_IRQENABLE_SET_LL);
+
+ /* Dummy read to make sure writes are complete */
+ __raw_readl(base + OMAP44XX_EMIF_IRQENABLE_SET_LL);
+
+ /* setup IRQ handlers */
+ r = request_threaded_irq(emif[emif_nr].irq,
+ emif_interrupt_handler,
+ emif_threaded_isr,
+ IRQF_SHARED, emif[emif_nr].pdev->name,
+ emif[emif_nr].pdev);
+ if (r) {
+ pr_err("%s: Failed: request_irq emif[%d] IRQ%d:%d\n",
+ __func__, emif_nr, emif[emif_nr].irq, r);
+ return r;
+ }
+
+ /*
+ * Even if we fail to make the irq wakeup capable, we are at risk only
+ * while going to suspend where the device is cooler, we might lose a
+ * bit of power due to pending interrupt preventing core from hitting
+ * low power state but we can continue to handle events in active use
+ * cases. So don't free interrupt on failure of marking wakeup capable,
+ * just warn and continue.
+ */
+ if (enable_irq_wake(emif[emif_nr].irq))
+ pr_err("%s: Failed: wakeupen emif[%d] IRQ%d\n", __func__,
+ emif_nr, emif[emif_nr].irq);
+
+ return 0;
+}
+
+static ssize_t emif_temperature_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u32 temperature;
+ if (dev == &(emif[EMIF1].pdev->dev))
+ temperature = emif_temperature_level[EMIF1];
+ else if (dev == &(emif[EMIF2].pdev->dev))
+ temperature = emif_temperature_level[EMIF2];
+ else
+ return 0;
+
+ return snprintf(buf, 20, "%u\n", temperature);
+}
+static DEVICE_ATTR(temperature, S_IRUGO, emif_temperature_show, NULL);
+
+static int __devinit omap_emif_probe(struct platform_device *pdev)
+{
+ int id;
+ struct resource *res;
+
+ if (!pdev)
+ return -EINVAL;
+
+ id = pdev->id;
+ emif[id].pdev = pdev;
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ pr_err("EMIF %i Invalid IRQ resource\n", id);
+ return -ENODEV;
+ }
+
+ emif[id].irq = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ pr_err("EMIF%i Invalid mem resource\n", id);
+ return -ENODEV;
+ }
+
+ emif[id].base = ioremap(res->start, SZ_1M);
+ if (!emif[id].base) {
+ pr_err("Could not ioremap EMIF%i\n", id);
+ return -ENOMEM;
+ }
+
+ pr_info("EMIF%d is enabled with IRQ%d\n", id, emif[id].irq);
+
+ emif[id].ddr_refresh_disabled = false;
+
+ return 0;
+}
+
+static int emif_init(struct omap_hwmod *oh, void *user)
+{
+ char *name = "omap_emif";
+ struct omap_device *od;
+ static int id;
+
+ od = omap_device_build(name, id, oh, NULL, 0, omap_emif_latency,
+ ARRAY_SIZE(omap_emif_latency), false);
+ WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+ name, oh->name);
+ id++;
+ return 0;
+
+}
+
+static void emif_calculate_regs(const struct emif_device_details *devices,
+ u32 freq, struct emif_regs *regs)
+{
+ u32 temp;
+ const struct lpddr2_addressing *addressing;
+ const struct lpddr2_timings *timings;
+ const struct lpddr2_min_tck *min_tck;
+ const struct lpddr2_device_info *cs0_device = devices->cs0_device;
+ const struct lpddr2_device_info *cs1_device = devices->cs1_device;
+
+ emif_assert(devices);
+ emif_assert(regs);
+ /*
+ * You can not have a device on CS1 without one on CS0
+ * So configuring EMIF without a device on CS0 doesn't
+ * make sense
+ */
+ emif_assert(cs0_device);
+ emif_assert(cs0_device->type != LPDDR2_TYPE_NVM);
+ /*
+ * If there is a device on CS1 it should be same type as CS0
+ * (or NVM. But NVM is not supported in this driver yet)
+ */
+ emif_assert((cs1_device == NULL) ||
+ (cs1_device->type == LPDDR2_TYPE_NVM) ||
+ (cs0_device->type == cs1_device->type));
+ emif_assert(freq <= MAX_LPDDR2_FREQ);
+
+ set_ddr_clk_period(freq);
+
+ /*
+ * The device on CS0 is used for all timing calculations
+ * There is only one set of registers for timings per EMIF. So, if the
+ * second CS(CS1) has a device, it should have the same timings as the
+ * device on CS0
+ */
+ timings = get_timings_table(cs0_device->device_timings, freq);
+ emif_assert(timings);
+ min_tck = cs0_device->min_tck;
+
+ temp =
+ addressing_table_index(cs0_device->type, cs0_device->density,
+ cs0_device->io_width);
+ emif_assert((temp >= 0));
+ addressing = &(lpddr2_jedec_addressing_table[temp]);
+ emif_assert(addressing);
+
+ regs->RL_final = timings->RL;
+ /*
+ * Initial value of EMIF_SDRAM_CONFIG corresponds to the base
+ * frequency - 19.2 MHz
+ */
+ regs->sdram_config_init =
+ get_sdram_config_reg(cs0_device, cs1_device, addressing,
+ RL_19_2_MHZ);
+
+ regs->sdram_config_final = regs->sdram_config_init;
+ mask_n_set(regs->sdram_config_final, OMAP44XX_REG_CL_SHIFT,
+ OMAP44XX_REG_CL_MASK, timings->RL);
+
+ regs->ref_ctrl = get_sdram_ref_ctrl(freq, addressing);
+ regs->ref_ctrl_derated = regs->ref_ctrl / 4;
+
+ regs->sdram_tim1 = get_sdram_tim_1_reg(timings, min_tck, addressing);
+
+ regs->sdram_tim1_derated =
+ get_sdram_tim_1_reg_derated(timings, min_tck, addressing);
+
+ regs->sdram_tim2 = get_sdram_tim_2_reg(timings, min_tck);
+
+ regs->sdram_tim3 = get_sdram_tim_3_reg(timings, min_tck, addressing);
+
+ regs->read_idle_ctrl_normal =
+ get_read_idle_ctrl_reg(LPDDR2_VOLTAGE_STABLE);
+
+ regs->read_idle_ctrl_volt_ramp =
+ get_read_idle_ctrl_reg(LPDDR2_VOLTAGE_RAMPING);
+
+ regs->zq_config_normal =
+ get_zq_config_reg(cs1_device, addressing, LPDDR2_VOLTAGE_STABLE);
+
+ regs->zq_config_volt_ramp =
+ get_zq_config_reg(cs1_device, addressing, LPDDR2_VOLTAGE_RAMPING);
+
+ regs->temp_alert_config =
+ get_temp_alert_config(cs1_device, addressing, false);
+
+ regs->temp_alert_config_derated =
+ get_temp_alert_config(cs1_device, addressing, true);
+
+ regs->emif_ddr_phy_ctlr_1_init =
+ get_ddr_phy_ctrl_1(EMIF_FREQ_19_2_MHZ, RL_19_2_MHZ);
+
+ regs->emif_ddr_phy_ctlr_1_final =
+ get_ddr_phy_ctrl_1(freq, regs->RL_final);
+
+ /* save the frequency in the struct to act as a tag when cached */
+ regs->freq = freq;
+
+ pr_debug("Calculated EMIF configuration register values "
+ "for %d MHz", freq / 1000000);
+ pr_debug("sdram_config_init\t\t: 0x%08x\n", regs->sdram_config_init);
+ pr_debug("sdram_config_final\t\t: 0x%08x\n", regs->sdram_config_final);
+ pr_debug("sdram_ref_ctrl\t\t: 0x%08x\n", regs->ref_ctrl);
+ pr_debug("sdram_ref_ctrl_derated\t\t: 0x%08x\n",
+ regs->ref_ctrl_derated);
+ pr_debug("sdram_tim_1_reg\t\t: 0x%08x\n", regs->sdram_tim1);
+ pr_debug("sdram_tim_1_reg_derated\t\t: 0x%08x\n",
+ regs->sdram_tim1_derated);
+ pr_debug("sdram_tim_2_reg\t\t: 0x%08x\n", regs->sdram_tim2);
+ pr_debug("sdram_tim_3_reg\t\t: 0x%08x\n", regs->sdram_tim3);
+ pr_debug("emif_read_idle_ctrl_normal\t: 0x%08x\n",
+ regs->read_idle_ctrl_normal);
+ pr_debug("emif_read_idle_ctrl_dvfs\t: 0x%08x\n",
+ regs->read_idle_ctrl_volt_ramp);
+ pr_debug("zq_config_reg_normal\t: 0x%08x\n", regs->zq_config_normal);
+ pr_debug("zq_config_reg_dvfs\t\t: 0x%08x\n", regs->zq_config_volt_ramp);
+ pr_debug("temp_alert_config\t: 0x%08x\n", regs->temp_alert_config);
+ pr_debug("emif_ddr_phy_ctlr_1_init\t: 0x%08x\n",
+ regs->emif_ddr_phy_ctlr_1_init);
+ pr_debug("emif_ddr_phy_ctlr_1_final\t: 0x%08x\n",
+ regs->emif_ddr_phy_ctlr_1_final);
+}
+
+/*
+ * get_regs() - gets the cached emif_regs structure for a given EMIF instance
+ * (emif_nr) for a given frequency(freq):
+ *
+ * As an optimization, only one cache array(that of EMIF1) if both EMIF1 and
+ * EMIF2 has identical devices
+ *
+ * If we do not have an entry corresponding to the frequency given, we
+ * allocate a new entry and calculate the values
+ */
+static struct emif_regs *get_regs(u32 emif_nr, u32 freq)
+{
+ int i;
+ struct emif_regs **regs_cache;
+ struct emif_regs *regs = NULL;
+
+ /*
+ * If EMIF2 has the same devices as EMIF1 use the register
+ * cache of EMIF1
+ */
+ if ((emif_nr == EMIF1) ||
+ ((emif_nr == EMIF2)
+ && (emif_devices[EMIF1] == emif_devices[EMIF2])))
+ regs_cache = emif1_regs_cache;
+ else
+ regs_cache = emif2_regs_cache;
+
+ for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+ if (regs_cache[i]->freq == freq) {
+ regs = regs_cache[i];
+ break;
+ }
+ }
+
+ /*
+ * If we don't have an entry for this frequency in the cache create one
+ * and calculate the values
+ */
+ if (!regs) {
+ regs = kmalloc(sizeof(struct emif_regs), GFP_ATOMIC);
+ if (!regs)
+ return NULL;
+ emif_calculate_regs(emif_devices[emif_nr], freq, regs);
+
+ /*
+ * Now look for an un-used entry in the cache and save the
+ * newly created struct. If there are no free entries
+ * over-write the last entry
+ */
+ for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++)
+ ;
+
+ if (i >= EMIF_MAX_NUM_FREQUENCIES) {
+ pr_warning("emif: emif regs_cache full - more number"
+ " of frequencies used than expected!!");
+ i = EMIF_MAX_NUM_FREQUENCIES - 1;
+ kfree(regs_cache[i]);
+ }
+ regs_cache[i] = regs;
+ }
+ return regs;
+}
+
+static int do_emif_setup_registers(u32 emif_nr, u32 freq, u32 volt_state)
+{
+ struct emif_regs *regs;
+ regs = get_regs(emif_nr, freq);
+ if (!regs)
+ return -ENOMEM;
+
+ emif_curr_regs[emif_nr] = regs;
+ setup_registers(emif_nr, regs, volt_state);
+ setup_temperature_sensitive_regs(emif_nr, regs);
+
+ return 0;
+}
+
+static int do_setup_device_details(u32 emif_nr,
+ const struct emif_device_details *devices)
+{
+ if (!emif_devices[emif_nr]) {
+ emif_devices[emif_nr] =
+ kmalloc(sizeof(struct emif_device_details), GFP_KERNEL);
+ if (!emif_devices[emif_nr])
+ return -ENOMEM;
+ *emif_devices[emif_nr] = *devices;
+ }
+
+ return 0;
+}
+
+/*
+ * Initialize the temperature level and setup the sysfs nodes
+ * and uvent for temperature monitoring
+ */
+static void init_temperature(u32 emif_nr)
+{
+ if (!emif_devices[emif_nr])
+ return;
+
+ emif_temperature_level[emif_nr] = get_temperature_level(emif_nr);
+ WARN_ON(device_create_file(&(emif[emif_nr].pdev->dev),
+ &dev_attr_temperature));
+ kobject_uevent(&(emif[emif_nr].pdev->dev.kobj), KOBJ_ADD);
+
+ if (emif_temperature_level[emif_nr] == SDRAM_TEMP_VERY_HIGH_SHUTDOWN)
+ pr_emerg("EMIF %d: SDRAM temperature exceeds operating"
+ "limit.. Needs shut down!!!", emif_nr + 1);
+}
+
+/*
+ * omap_emif_device_init needs to be done before
+ * ddr reconfigure function call.
+ * Hence omap_emif_device_init is a postcore_initcall.
+ */
+static int __init omap_emif_device_init(void)
+{
+ /*
+ * To avoid code running on other OMAPs in
+ * multi-omap builds
+ */
+ if (!cpu_is_omap44xx())
+ return -ENODEV;
+
+ return omap_hwmod_for_each_by_class("emif", emif_init, NULL);
+}
+postcore_initcall(omap_emif_device_init);
+
+
+/* We need to disable interrupts of the EMIF
+ * module, because in a warm reboot scenario, there
+ * may be a pending irq that is not serviced and emif
+ * is stuck in transition. On the next boot HW mod
+ * fails emif inizalization with a timeout.
+ */
+void emif_clear_irq(int emif_id)
+{
+ u32 irq_mask = 0;
+ u32 base = 0;
+ u32 reg = 0;
+
+ if (emif_id == 0)
+ base = OMAP44XX_EMIF1_VIRT;
+ else
+ base = OMAP44XX_EMIF2_VIRT;
+
+ /* Disable the relevant interrupts for both LL and SYS */
+ irq_mask = OMAP44XX_REG_EN_TA_SYS_MASK | OMAP44XX_REG_EN_ERR_SYS_MASK
+ | OMAP44XX_REG_EN_DNV_SYS_MASK;
+ __raw_writel(irq_mask, base + OMAP44XX_EMIF_IRQENABLE_CLR_SYS);
+ __raw_writel(irq_mask, base + OMAP44XX_EMIF_IRQENABLE_CLR_LL);
+
+ /* Clear any pendining interrupts without overwritng reserved bits*/
+ reg = __raw_readl(base + OMAP44XX_EMIF_IRQSTATUS_SYS);
+ reg |= irq_mask;
+ __raw_writel(reg, base + OMAP44XX_EMIF_IRQSTATUS_SYS);
+
+ reg = __raw_readl(base + OMAP44XX_EMIF_IRQSTATUS_LL);
+ reg |= irq_mask;
+ __raw_writel(reg, base + OMAP44XX_EMIF_IRQSTATUS_LL);
+
+ /* Dummy read to make sure writes are complete */
+ __raw_readl(base + OMAP44XX_EMIF_IRQENABLE_SET_LL);
+
+ return;
+}
+
+void emif_driver_shutdown(struct platform_device *pdev)
+{
+ emif_clear_irq(pdev->id);
+}
+
+static struct platform_driver omap_emif_driver = {
+ .probe = omap_emif_probe,
+ .driver = {
+ .name = "omap_emif",
+ },
+
+ .shutdown = emif_driver_shutdown,
+};
+
+static int __init omap_emif_register(void)
+{
+ return platform_driver_register(&omap_emif_driver);
+}
+postcore_initcall(omap_emif_register);
+
+/*
+ * omap_emif_notify_voltage - setup the voltage sensitive
+ * registers based on the voltage situation (voltage ramping or stable)
+ * read_idle_ctrl and zq_config are the registers that are voltage sensitive
+ * They need to have a very safe value(more frequent zq calibration and
+ * read idle forcing) when voltage is scaling and can have a more relaxed
+ * nominal value(frequency dependent) when voltage is stable
+ */
+int omap_emif_notify_voltage(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ u32 volt_state;
+
+ if (val == OMAP_VOLTAGE_PRECHANGE)
+ volt_state = LPDDR2_VOLTAGE_RAMPING;
+ else
+ volt_state = LPDDR2_VOLTAGE_STABLE;
+
+ if (likely(emif_curr_regs[EMIF1]))
+ setup_volt_sensitive_registers(EMIF1, emif_curr_regs[EMIF1],
+ volt_state);
+
+ if (likely(emif_curr_regs[EMIF2]))
+ setup_volt_sensitive_registers(EMIF2, emif_curr_regs[EMIF2],
+ volt_state);
+
+ if (unlikely(!emif_curr_regs[EMIF1] && !emif_curr_regs[EMIF2])) {
+ pr_err_once("emif: voltage state notification came before the"
+ " initial setup - ignoring the notification");
+ return -EINVAL;
+ }
+
+ /*
+ * EMIF read-idle control needs to be setup using
+ * freq update method only
+ */
+ return omap4_prcm_freq_update();
+}
+
+static struct notifier_block emif_volt_notifier_block = {
+ .notifier_call = omap_emif_notify_voltage,
+};
+
+static int __init omap_emif_late_init(void)
+{
+ struct voltagedomain *voltdm = voltdm_lookup("core");
+
+ if (!voltdm) {
+ pr_err("CORE voltage domain lookup failed\n");
+ return -EINVAL;
+ }
+
+ voltdm_register_notifier(voltdm, &emif_volt_notifier_block);
+
+ return 0;
+}
+late_initcall(omap_emif_late_init);
+
+/*
+ * omap_emif_setup_registers - setup the shadow registers for a given
+ * frequency. This will be typically followed by a FREQ_UPDATE procedure
+ * to lock at the new frequency and this will update the EMIF main registers
+ * with shadow register values
+ */
+int omap_emif_setup_registers(u32 freq, u32 volt_state)
+{
+ int err = 0;
+ if (likely(emif_devices[EMIF1]))
+ err = do_emif_setup_registers(EMIF1, freq, volt_state);
+ if (likely(!err && emif_devices[EMIF2]))
+ err = do_emif_setup_registers(EMIF2, freq, volt_state);
+ return err;
+}
+
+
+/*
+ * omap_emif_frequency_pre_notify - Disable DDR self refresh of both EMIFs
+ *
+ * It disables the LP mode if the LP mode of EMIFs was LP_MODE_SELF_REFRESH.
+ *
+ * It should be called before any PRCM frequency update sequence.
+ * After the frequency update sequence, omap_emif_frequency_post_notify
+ * should be called to restore the original LP MODE setting of the EMIFs.
+ *
+ */
+void omap_emif_frequency_pre_notify(void)
+{
+ int emif_num;
+
+ for (emif_num = EMIF1; emif_num < EMIF_NUM_INSTANCES; emif_num++) {
+
+ /*
+ * Only disable ddr self-refresh
+ * if ddr self-refresh was enabled
+ */
+ if (likely(LP_MODE_SELF_REFRESH == get_lp_mode(emif_num))) {
+
+ set_lp_mode(emif_num, LP_MODE_DISABLE);
+ emif[emif_num].ddr_refresh_disabled = true;
+ }
+
+ }
+}
+
+/*
+ * omap_emif_frequency_post_notify - Enable DDR self refresh of both EMIFs
+ *
+ * It restores the LP mode of the EMIFs back to LP_MODE_SELF_REFRESH if it
+ * was previously disabled by omap_emif_frequency_pre_notify()
+ *
+ */
+void omap_emif_frequency_post_notify(void)
+{
+ int emif_num;
+
+ for (emif_num = EMIF1; emif_num < EMIF_NUM_INSTANCES; emif_num++) {
+
+ /*
+ * Only re-enable ddr self-refresh
+ * if ddr self-refresh was disabled
+ */
+ if (likely(emif[emif_num].ddr_refresh_disabled)) {
+
+ set_lp_mode(emif_num, LP_MODE_SELF_REFRESH);
+ emif[emif_num].ddr_refresh_disabled = false;
+ }
+ }
+}
+
+/*
+ * omap_emif_setup_device_details - save the SDRAM device details passed
+ * from the board file
+ */
+int omap_emif_setup_device_details(const struct emif_device_details
+ *emif1_devices,
+ const struct emif_device_details
+ *emif2_devices)
+{
+ if (emif1_devices)
+ BUG_ON(do_setup_device_details(EMIF1, emif1_devices));
+
+ /*
+ * If memory devices connected to both the EMIFs are identical
+ * (which is normally the case), then no need to calculate the
+ * registers again for EMIF1 and allocate the structure for registers
+ */
+ if (emif2_devices && (emif1_devices != emif2_devices))
+ BUG_ON(do_setup_device_details(EMIF2, emif2_devices));
+ else if (emif2_devices) {
+ emif_devices[EMIF2] = emif_devices[EMIF1];
+ /* call for temperature related setup */
+ BUG_ON(do_setup_device_details(EMIF2, emif2_devices));
+ }
+
+ return 0;
+}
+
+static void __init setup_lowpower_regs(u32 emif_nr,
+ struct emif_device_details *emif_dev)
+{
+ u32 temp;
+ void __iomem *base = emif[emif_nr].base;
+ const struct lpddr2_device_info *dev;
+
+ if (!emif_dev) {
+ pr_err("%s: no emif %d\n", __func__, emif_nr);
+ return;
+ }
+
+ /*
+ * All devices on this specific EMIF should have the same Selfrefresh
+ * timing, so use cs0
+ */
+ dev = emif_dev->cs0_device;
+ if (!dev) {
+ pr_err("%s: no CS0 device in emif %d\n", __func__, emif_nr);
+ return;
+ }
+ if (dev->emif_ddr_selfrefresh_cycles >= 0) {
+ u32 num_cycles, ddr_sr_timer;
+
+ /* Enable self refresh if not already configured */
+ temp = __raw_readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL) &
+ OMAP44XX_REG_LP_MODE_MASK;
+ /*
+ * Configure the self refresh timing
+ * base value starts at 16 cycles mapped to 1( __fls(16) = 4)
+ */
+ num_cycles = dev->emif_ddr_selfrefresh_cycles;
+ if (num_cycles >= 16)
+ ddr_sr_timer = __fls(num_cycles) - 3;
+ else
+ ddr_sr_timer = 0;
+
+ /* Program the idle delay */
+ temp = __raw_readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW);
+ mask_n_set(temp, OMAP44XX_REG_SR_TIM_SHDW_SHIFT,
+ OMAP44XX_REG_SR_TIM_SHDW_MASK, ddr_sr_timer);
+ /*
+ * Some weird magic number to a field which should'nt impact..
+ * but seems to make this work..
+ */
+ mask_n_set(temp, OMAP44XX_REG_CS_TIM_SHDW_SHIFT,
+ OMAP44XX_REG_CS_TIM_SHDW_MASK, 0xf);
+ __raw_writel(temp, base + OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW);
+
+ /* Enable Self Refresh */
+ temp = __raw_readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+ mask_n_set(temp, OMAP44XX_REG_LP_MODE_SHIFT,
+ OMAP44XX_REG_LP_MODE_MASK, LP_MODE_SELF_REFRESH);
+ __raw_writel(temp, base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+ } else {
+ /* Disable Automatic power management if < 0 and not disabled */
+ temp = __raw_readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL) &
+ OMAP44XX_REG_LP_MODE_MASK;
+
+ temp = __raw_readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW);
+ mask_n_set(temp, OMAP44XX_REG_SR_TIM_SHDW_SHIFT,
+ OMAP44XX_REG_SR_TIM_SHDW_MASK, 0x0);
+ __raw_writel(temp, base + OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW);
+
+ temp = __raw_readl(base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+ mask_n_set(temp, OMAP44XX_REG_LP_MODE_SHIFT,
+ OMAP44XX_REG_LP_MODE_MASK, LP_MODE_DISABLE);
+ __raw_writel(temp, base + OMAP44XX_EMIF_PWR_MGMT_CTRL);
+ }
+}
+
+/*
+ * omap_init_emif_timings - reprogram EMIF timing parameters
+ *
+ * Sets the CORE DPLL3 M2 divider to the same value that it's at
+ * currently. This has the effect of setting the EMIF DDR AC timing
+ * registers to the values currently defined by the kernel.
+ */
+static int __init omap_init_emif_timings(void)
+{
+ struct clk *dpll_core_m2_clk;
+ int ret;
+ long rate;
+
+ /*
+ * Setup the initial temperatures sysfs nodes etc.
+ * Subsequent updates to temperature is done through interrupts
+ */
+ init_temperature(EMIF1);
+ init_temperature(EMIF2);
+
+ /* FREQ_UPDATE sequence isn't supported on early vesion */
+ if (omap_rev() == OMAP4430_REV_ES1_0)
+ return -EINVAL;
+
+ dpll_core_m2_clk = clk_get(NULL, "dpll_core_m2_ck");
+ if (!dpll_core_m2_clk)
+ pr_err("Could not get LPDDR2 clock - dpll_core_m2_ck\n");
+
+ rate = clk_get_rate(dpll_core_m2_clk);
+ pr_info("Reprogramming LPDDR2 timings to %ld Hz\n", rate >> 1);
+
+ ret = clk_set_rate(dpll_core_m2_clk, rate);
+ if (ret)
+ pr_err("Unable to set LPDDR2 rate to %ld:\n", rate);
+
+ /* registers are setup correctly - now enable interrupts */
+ if (emif_devices[EMIF1]) {
+ ret = setup_emif_interrupts(EMIF1);
+ setup_lowpower_regs(EMIF1, emif_devices[EMIF1]);
+ }
+ if (!ret && emif_devices[EMIF2]) {
+ ret = setup_emif_interrupts(EMIF2);
+ setup_lowpower_regs(EMIF2, emif_devices[EMIF2]);
+ }
+
+ clk_put(dpll_core_m2_clk);
+
+ return ret;
+}
+late_initcall(omap_init_emif_timings);
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9529842..1045c72 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -23,6 +23,9 @@
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
static struct omap_device_pm_latency omap_gpio_latency[] = {
[0] = {
@@ -39,6 +42,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
struct omap_gpio_dev_attr *dev_attr;
char *name = "omap_gpio";
int id;
+ struct powerdomain *pwrdm;
/*
* extract the device id from name field available in the
@@ -58,16 +62,77 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
dev_attr = (struct omap_gpio_dev_attr *)oh->dev_attr;
pdata->bank_width = dev_attr->bank_width;
+ pdata->suspend_support = true;
pdata->dbck_flag = dev_attr->dbck_flag;
pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
+ pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("gpio%d: Memory allocation failed\n", id);
+ return -ENOMEM;
+ }
+
+ pdata->regs->irqctrl = USHRT_MAX;
+ pdata->regs->edgectrl1 = USHRT_MAX;
+ pdata->regs->edgectrl2 = USHRT_MAX;
+
switch (oh->class->rev) {
case 0:
+ if (id == 1)
+ /* non-wakeup GPIO pins for OMAP2 Bank1 */
+ pdata->non_wakeup_gpios = 0xe203ffc0;
+ else if (id == 2)
+ /* non-wakeup GPIO pins for OMAP2 Bank2 */
+ pdata->non_wakeup_gpios = 0x08700040;
+ /* fall through */
+
case 1:
- pdata->bank_type = METHOD_GPIO_24XX;
+ pdata->regs->revision = OMAP24XX_GPIO_REVISION;
+ pdata->regs->direction = OMAP24XX_GPIO_OE;
+ pdata->regs->datain = OMAP24XX_GPIO_DATAIN;
+ pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT;
+ pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT;
+ pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT;
+ pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1;
+ pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2;
+ pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1;
+ pdata->regs->irqenable2 = OMAP24XX_GPIO_IRQENABLE2;
+ pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1;
+ pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1;
+ pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL;
+ pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN;
+ pdata->regs->ctrl = OMAP24XX_GPIO_CTRL;
+ pdata->regs->wkup_status = OMAP24XX_GPIO_WAKE_EN;
+ pdata->regs->wkup_clear = OMAP24XX_GPIO_CLEARWKUENA;
+ pdata->regs->wkup_set = OMAP24XX_GPIO_SETWKUENA;
+ pdata->regs->leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0;
+ pdata->regs->leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1;
+ pdata->regs->risingdetect = OMAP24XX_GPIO_RISINGDETECT;
+ pdata->regs->fallingdetect = OMAP24XX_GPIO_FALLINGDETECT;
break;
case 2:
- pdata->bank_type = METHOD_GPIO_44XX;
+ pdata->regs->revision = OMAP4_GPIO_REVISION;
+ pdata->regs->direction = OMAP4_GPIO_OE;
+ pdata->regs->datain = OMAP4_GPIO_DATAIN;
+ pdata->regs->dataout = OMAP4_GPIO_DATAOUT;
+ pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT;
+ pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT;
+ pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0;
+ pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1;
+ pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0;
+ pdata->regs->irqenable2 = OMAP4_GPIO_IRQSTATUSSET1;
+ pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0;
+ pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0;
+ pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME;
+ pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE;
+ pdata->regs->ctrl = OMAP4_GPIO_CTRL;
+ pdata->regs->wkup_status = OMAP4_GPIO_IRQWAKEN0;
+ pdata->regs->wkup_clear = OMAP4_GPIO_IRQWAKEN0;
+ pdata->regs->wkup_set = OMAP4_GPIO_IRQWAKEN0;
+ pdata->regs->leveldetect0 = OMAP4_GPIO_LEVELDETECT0;
+ pdata->regs->leveldetect1 = OMAP4_GPIO_LEVELDETECT1;
+ pdata->regs->risingdetect = OMAP4_GPIO_RISINGDETECT;
+ pdata->regs->fallingdetect = OMAP4_GPIO_FALLINGDETECT;
break;
default:
WARN(1, "Invalid gpio bank_type\n");
@@ -75,6 +140,9 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
return -EINVAL;
}
+ pwrdm = omap_hwmod_get_pwrdm(oh);
+ pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+
od = omap_device_build(name, id - 1, oh, pdata,
sizeof(*pdata), omap_gpio_latency,
ARRAY_SIZE(omap_gpio_latency),
@@ -87,7 +155,6 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
return PTR_ERR(od);
}
- gpio_bank_count++;
return 0;
}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index dfffbbf..5610d10 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -78,9 +78,9 @@ struct gpmc_cs_config {
/*
* Structure to save/restore gpmc context
- * to support core off on OMAP3
+ * to support core off.
*/
-struct omap3_gpmc_regs {
+struct omap_gpmc_regs {
u32 sysconfig;
u32 irqenable;
u32 timeout_ctrl;
@@ -776,10 +776,9 @@ static irqreturn_t gpmc_handle_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap3_gpmc_regs gpmc_context;
+static struct omap_gpmc_regs gpmc_context;
-void omap3_gpmc_save_context(void)
+void omap_gpmc_save_context(void)
{
int i;
@@ -811,7 +810,7 @@ void omap3_gpmc_save_context(void)
}
}
-void omap3_gpmc_restore_context(void)
+void omap_gpmc_restore_context(void)
{
int i;
@@ -841,7 +840,6 @@ void omap3_gpmc_restore_context(void)
}
}
}
-#endif /* CONFIG_ARCH_OMAP3 */
/**
* gpmc_enable_hwecc - enable hardware ecc functionality
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 66868c5..0201705 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -31,16 +31,6 @@ static u16 control_mmc1;
#define HSMMC_NAME_LEN 9
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
-
-static int hsmmc_get_context_loss(struct device *dev)
-{
- return omap_pm_get_dev_context_loss_count(dev);
-}
-
-#else
-#define hsmmc_get_context_loss NULL
-#endif
static void omap_hsmmc1_before_set_reg(struct device *dev, int slot,
int power_on, int vdd)
@@ -318,8 +308,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
else
mmc->reg_offset = 0;
- mmc->get_context_loss_count = hsmmc_get_context_loss;
-
mmc->slots[0].switch_pin = c->gpio_cd;
mmc->slots[0].gpio_wp = c->gpio_wp;
@@ -344,6 +332,20 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
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;
+ }
+
+ if (c->mmc_data) {
+ memcpy(&mmc->slots[0].mmc_data, c->mmc_data,
+ sizeof(struct mmc_platform_data));
+ mmc->slots[0].card_detect =
+ (mmc_card_detect_func)c->mmc_data->status;
+ }
+
/*
* 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 f757e78..2cbe0f9 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -6,8 +6,12 @@
* published by the Free Software Foundation.
*/
+#include <asm/mach/mmc.h>
+
struct mmc_card;
+typedef int (*mmc_card_detect_func)(struct device *dev, int slot);
+
struct omap2_hsmmc_info {
u8 mmc; /* controller 1/2/3 */
u32 caps; /* 4/8 wires and any additional host
@@ -25,6 +29,7 @@ struct omap2_hsmmc_info {
char *name; /* or NULL for default */
struct device *dev; /* returned: pointer to mmc adapter */
int ocr_mask; /* temporary HACK */
+ struct mmc_platform_data *mmc_data;
/* Remux (pad configuration) when powering on/off */
void (*remux)(struct device *dev, int slot, int power_on);
/* init some special card */
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 2537090..a90630d 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -32,6 +32,7 @@ static struct omap_chip_id omap_chip;
static unsigned int omap_revision;
u32 omap3_features;
+u32 omap4_features;
unsigned int omap_rev(void)
{
@@ -88,6 +89,8 @@ EXPORT_SYMBOL(omap_type);
#define OMAP_TAP_DIE_ID_44XX_1 0x0208
#define OMAP_TAP_DIE_ID_44XX_2 0x020c
#define OMAP_TAP_DIE_ID_44XX_3 0x0210
+#define OMAP_TAP_PROD_ID_44XX_0 0x0214
+#define OMAP_TAP_PROD_ID_44XX_1 0x0218
#define read_tap_reg(reg) __raw_readl(tap_base + (reg))
@@ -126,6 +129,16 @@ void omap_get_die_id(struct omap_die_id *odi)
odi->id_3 = read_tap_reg(OMAP_TAP_DIE_ID_3);
}
+void omap_get_production_id(struct omap_die_id *odi)
+{
+ if (cpu_is_omap44xx()) {
+ odi->id_0 = read_tap_reg(OMAP_TAP_PROD_ID_44XX_0);
+ odi->id_1 = read_tap_reg(OMAP_TAP_PROD_ID_44XX_1);
+ odi->id_2 = 0;
+ odi->id_3 = 0;
+ }
+}
+
static void __init omap24xx_check_revision(void)
{
int i, j;
@@ -212,6 +225,34 @@ static void __init omap3_check_features(void)
*/
}
+static void __init omap4_check_features(void)
+{
+ u32 si_type;
+
+ omap4_features = 0;
+
+ if (cpu_is_omap443x())
+ omap4_features |= OMAP4_HAS_MPU_1GHZ;
+
+
+ if (cpu_is_omap446x()) {
+ si_type =
+ read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
+ switch ((si_type & (3 << 16)) >> 16) {
+ case 2:
+ /* High performance device */
+ omap4_features |= OMAP4_HAS_MPU_1_5GHZ;
+ omap4_features |= OMAP4_HAS_MPU_1_2GHZ;
+ break;
+ case 1:
+ default:
+ /* Standard device */
+ omap4_features |= OMAP4_HAS_MPU_1_2GHZ;
+ break;
+ }
+ }
+}
+
static void __init ti816x_check_features(void)
{
omap3_features = OMAP3_HAS_NEON;
@@ -331,8 +372,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 +390,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 +423,19 @@ static void __init omap4_check_revision(void)
omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
}
break;
+ case 0xb94e:
+ switch (rev) {
+ case 0:
+ omap_revision = OMAP4460_REV_ES1_0;
+ omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
+ break;
+ case 2:
+ default:
+ omap_revision = OMAP4460_REV_ES1_1;
+ omap_chip.oc |= CHIP_IS_OMAP4460ES1_1;
+ break;
+ }
+ break;
default:
/* Unknown default to latest silicon rev as default */
omap_revision = OMAP4430_REV_ES2_2;
@@ -518,6 +577,7 @@ void __init omap2_check_revision(void)
return;
} else if (cpu_is_omap44xx()) {
omap4_check_revision();
+ omap4_check_features();
return;
} else {
pr_err("OMAP revision unknown, please fix!\n");
diff --git a/arch/arm/mach-omap2/include/mach/barriers.h b/arch/arm/mach-omap2/include/mach/barriers.h
new file mode 100644
index 0000000..aa72a33
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/barriers.h
@@ -0,0 +1,48 @@
+/*
+ * OMAP memory barrier header.
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Richard Woodruff <r-woodruff2@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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __MACH_BARRIERS_H
+#define __MACH_BARRIERS_H
+
+#include <linux/types.h>
+
+/* provide func ptr so to allow safe calling at any point */
+struct omap_bus_post_fns {
+ void (*sync)(void);
+};
+
+extern struct omap_bus_post_fns omap_bus_post;
+
+#ifdef CONFIG_ARCH_OMAP4
+static inline void bus_sync(void)
+{
+ omap_bus_post.sync();
+}
+#else
+static inline void bus_sync(void)
+{ }
+#endif
+
+#define rmb() dsb()
+#define wmb() do { dsb(); outer_sync(); bus_sync(); } while (0)
+#define mb() wmb()
+
+#endif /* __MACH_BARRIERS_H */
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
index 2f7ac70..58983a1 100644
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
@@ -163,6 +163,7 @@
/* STD_FUSE_OPP_BGAP */
#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT 0
#define OMAP4_STD_FUSE_OPP_BGAP_MASK (0xffffffff << 0)
+#define OMAP4_STD_FUSE_OPP_BGAP_MASK_LSB (0xffff << 16)
/* STD_FUSE_OPP_DPLL_0 */
#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT 0
@@ -257,18 +258,50 @@
#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK (0x1f << 0)
/* TEMP_SENSOR */
-#define OMAP4_BGAP_TEMPSOFF_SHIFT 12
-#define OMAP4_BGAP_TEMPSOFF_MASK (1 << 12)
-#define OMAP4_BGAP_TSHUT_SHIFT 11
-#define OMAP4_BGAP_TSHUT_MASK (1 << 11)
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT 10
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK (1 << 10)
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT 9
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK (1 << 9)
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT 8
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 8)
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK (0xff << 0)
+#define OMAP4_BGAP_TEMPSOFF_SHIFT 13
+#define OMAP4_BGAP_TEMPSOFF_MASK (1 << 13)
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT 12
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK (1 << 12)
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT 11
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK (1 << 11)
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT 10
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 10)
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0)
+
+/* BANDGAP_CTRL */
+#define OMAP4_SINGLE_MODE_SHIFT 31
+#define OMAP4_SINGLE_MODE_MASK (1 << 31)
+#define OMAP4_MASK_HOT_SHIFT 1
+#define OMAP4_MASK_HOT_MASK (1 << 1)
+#define OMAP4_MASK_COLD_SHIFT 0
+#define OMAP4_MASK_COLD_MASK (1 << 0)
+
+/* BANDGAP_COUNTER */
+#define OMAP4_COUNTER_SHIFT 0
+#define OMAP4_COUNTER_MASK (0xffffff << 0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP4_T_HOT_SHIFT 16
+#define OMAP4_T_HOT_MASK (0x3ff << 16)
+#define OMAP4_T_COLD_SHIFT 0
+#define OMAP4_T_COLD_MASK (0x3ff << 0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP4_TSHUT_HOT_SHIFT 16
+#define OMAP4_TSHUT_HOT_MASK (0x3ff << 16)
+#define OMAP4_TSHUT_COLD_SHIFT 0
+#define OMAP4_TSHUT_COLD_MASK (0x3ff << 0)
+
+/* BANDGAP_STATUS */
+#define OMAP4_CLEAN_STOP_SHIFT 3
+#define OMAP4_CLEAN_STOP_MASK (1 << 3)
+#define OMAP4_BGAP_ALERT_SHIFT 2
+#define OMAP4_BGAP_ALERT_MASK (1 << 2)
+#define OMAP4_HOT_FLAG_SHIFT 1
+#define OMAP4_HOT_FLAG_MASK (1 << 1)
+#define OMAP4_COLD_FLAG_SHIFT 0
+#define OMAP4_COLD_FLAG_MASK (1 << 0)
/* DPLL_NWELL_TRIM_0 */
#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT 29
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
index c88420d..852a3a9 100644
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
@@ -1185,6 +1185,14 @@
#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK (1 << 13)
#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT 12
#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK (1 << 12)
+#define OMAP4_LPDDR21_VREF_EN_CA_SHIFT 3
+#define OMAP4_LPDDR21_VREF_EN_CA_MASK (1 << 3)
+#define OMAP4_LPDDR21_VREF_EN_DQ_SHIFT 2
+#define OMAP4_LPDDR21_VREF_EN_DQ_MASK (1 << 2)
+#define OMAP4_LPDDR21_VREF_AUTO_EN_CA_SHIFT 1
+#define OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK (1 << 1)
+#define OMAP4_LPDDR21_VREF_AUTO_EN_DQ_SHIFT 0
+#define OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK (1 << 0)
/* CONTROL_LPDDR2IO2_0 */
#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT 30
diff --git a/arch/arm/mach-omap2/include/mach/dmm-44xx.h b/arch/arm/mach-omap2/include/mach/dmm-44xx.h
new file mode 100644
index 0000000..c25dda5
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dmm-44xx.h
@@ -0,0 +1,363 @@
+/*
+ * OMAP44xx DMM_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * 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_DMM_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_DMM_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP44XX_DMM__DMM 0x4e000000
+
+/* Registers offset */
+#define OMAP44XX_DMM_REVISION 0x0000
+#define OMAP44XX_DMM_HWINFO 0x0004
+#define OMAP44XX_DMM_LISA_HWINFO 0x0008
+#define OMAP44XX_DMM_SYSCONFIG 0x0010
+#define OMAP44XX_DMM_LISA_LOCK 0x001c
+#define OMAP44XX_DMM_LISA_MAP 0x0040
+#define OMAP44XX_DMM_TILER_HWINFO 0x0208
+#define OMAP44XX_DMM_TILER_OR 0x0220
+#define OMAP44XX_DMM_PAT_HWINFO 0x0408
+#define OMAP44XX_DMM_PAT_GEOMETRY 0x040c
+#define OMAP44XX_DMM_PAT_CONFIG 0x0410
+#define OMAP44XX_DMM_PAT_VIEW 0x0420
+#define OMAP44XX_DMM_PAT_VIEW_MAP 0x0440
+#define OMAP44XX_DMM_PAT_VIEW_MAP_BASE 0x0460
+#define OMAP44XX_DMM_PAT_IRQ_EOI 0x0478
+#define OMAP44XX_DMM_PAT_IRQSTATUS_RAW 0x0480
+#define OMAP44XX_DMM_PAT_IRQSTATUS 0x0490
+#define OMAP44XX_DMM_PAT_IRQENABLE_SET 0x04a0
+#define OMAP44XX_DMM_PAT_IRQENABLE_CLR 0x04b0
+#define OMAP44XX_DMM_PAT_STATUS 0x04c0
+#define OMAP44XX_DMM_PAT_DESCR 0x0500
+#define OMAP44XX_DMM_PAT_AREA 0x0504
+#define OMAP44XX_DMM_PAT_CTRL 0x0508
+#define OMAP44XX_DMM_PAT_DATA 0x050c
+#define OMAP44XX_DMM_PEG_HWINFO 0x0608
+#define OMAP44XX_DMM_PEG_PRIO 0x0620
+#define OMAP44XX_DMM_PEG_PRIO_PAT 0x0640
+
+/* Registers shifts and masks */
+
+/* DMM_REVISION */
+#define OMAP44XX_SCHEME_SHIFT 30
+#define OMAP44XX_SCHEME_MASK (0x3 << 30)
+#define OMAP44XX_FUNC_SHIFT 16
+#define OMAP44XX_FUNC_MASK (0xfff << 16)
+#define OMAP44XX_R_RTL_SHIFT 11
+#define OMAP44XX_R_RTL_MASK (0x1f << 11)
+#define OMAP44XX_X_MAJOR_SHIFT 8
+#define OMAP44XX_X_MAJOR_MASK (0x7 << 8)
+#define OMAP44XX_CUSTOM_SHIFT 6
+#define OMAP44XX_CUSTOM_MASK (0x3 << 6)
+#define OMAP44XX_Y_MINOR_SHIFT 0
+#define OMAP44XX_Y_MINOR_MASK (0x3f << 0)
+
+/* DMM_HWINFO */
+#define OMAP44XX_ROBIN_CNT_SHIFT 16
+#define OMAP44XX_ROBIN_CNT_MASK (0xf << 16)
+#define OMAP44XX_ELLA_CNT_SHIFT 8
+#define OMAP44XX_ELLA_CNT_MASK (0xf << 8)
+#define OMAP44XX_TILER_CNT_SHIFT 0
+#define OMAP44XX_TILER_CNT_MASK (0xf << 0)
+
+/* DMM_LISA_HWINFO */
+#define OMAP44XX_SDRC_CNT_SHIFT 8
+#define OMAP44XX_SDRC_CNT_MASK (0xf << 8)
+#define OMAP44XX_SECTION_CNT_SHIFT 0
+#define OMAP44XX_SECTION_CNT_MASK (0x1f << 0)
+
+/* DMM_SYSCONFIG */
+#define OMAP44XX_IDLE_MODE_SHIFT 2
+#define OMAP44XX_IDLE_MODE_MASK (0x3 << 2)
+
+/* DMM_LISA_LOCK */
+#define OMAP44XX_LOCK_SHIFT 0
+#define OMAP44XX_LOCK_MASK (1 << 0)
+
+/* DMM_LISA_MAP */
+#define OMAP44XX_SYS_ADDR_SHIFT 24
+#define OMAP44XX_SYS_ADDR_MASK (0xff << 24)
+#define OMAP44XX_SYS_SIZE_SHIFT 20
+#define OMAP44XX_SYS_SIZE_MASK (0x7 << 20)
+#define OMAP44XX_SDRC_INTL_SHIFT 18
+#define OMAP44XX_SDRC_INTL_MASK (0x3 << 18)
+#define OMAP44XX_SDRC_ADDRSPC_SHIFT 16
+#define OMAP44XX_SDRC_ADDRSPC_MASK (0x3 << 16)
+#define OMAP44XX_SDRC_MAP_SHIFT 8
+#define OMAP44XX_SDRC_MAP_MASK (0x3 << 8)
+#define OMAP44XX_SDRC_ADDR_SHIFT 0
+#define OMAP44XX_SDRC_ADDR_MASK (0xff << 0)
+
+/* DMM_TILER_HWINFO */
+#define OMAP44XX_OR_CNT_SHIFT 0
+#define OMAP44XX_OR_CNT_MASK (0x7f << 0)
+
+/* DMM_TILER_OR */
+#define OMAP44XX_W7_SHIFT 31
+#define OMAP44XX_W7_MASK (1 << 31)
+#define OMAP44XX_OR7_SHIFT 28
+#define OMAP44XX_OR7_MASK (0x7 << 28)
+#define OMAP44XX_W6_SHIFT 27
+#define OMAP44XX_W6_MASK (1 << 27)
+#define OMAP44XX_OR6_SHIFT 24
+#define OMAP44XX_OR6_MASK (0x7 << 24)
+#define OMAP44XX_W5_SHIFT 23
+#define OMAP44XX_W5_MASK (1 << 23)
+#define OMAP44XX_OR5_SHIFT 20
+#define OMAP44XX_OR5_MASK (0x7 << 20)
+#define OMAP44XX_W4_SHIFT 19
+#define OMAP44XX_W4_MASK (1 << 19)
+#define OMAP44XX_OR4_SHIFT 16
+#define OMAP44XX_OR4_MASK (0x7 << 16)
+#define OMAP44XX_W3_SHIFT 15
+#define OMAP44XX_W3_MASK (1 << 15)
+#define OMAP44XX_OR3_SHIFT 12
+#define OMAP44XX_OR3_MASK (0x7 << 12)
+#define OMAP44XX_W2_SHIFT 11
+#define OMAP44XX_W2_MASK (1 << 11)
+#define OMAP44XX_OR2_SHIFT 8
+#define OMAP44XX_OR2_MASK (0x7 << 8)
+#define OMAP44XX_W1_SHIFT 7
+#define OMAP44XX_W1_MASK (1 << 7)
+#define OMAP44XX_OR1_SHIFT 4
+#define OMAP44XX_OR1_MASK (0x7 << 4)
+#define OMAP44XX_W0_SHIFT 3
+#define OMAP44XX_W0_MASK (1 << 3)
+#define OMAP44XX_OR0_SHIFT 0
+#define OMAP44XX_OR0_MASK (0x7 << 0)
+
+/* DMM_PAT_HWINFO */
+#define OMAP44XX_ENGINE_CNT_SHIFT 24
+#define OMAP44XX_ENGINE_CNT_MASK (0x1f << 24)
+#define OMAP44XX_LUT_CNT_SHIFT 16
+#define OMAP44XX_LUT_CNT_MASK (0x1f << 16)
+#define OMAP44XX_VIEW_MAP_CNT_SHIFT 8
+#define OMAP44XX_VIEW_MAP_CNT_MASK (0xf << 8)
+#define OMAP44XX_VIEW_CNT_SHIFT 0
+#define OMAP44XX_VIEW_CNT_MASK (0x7f << 0)
+
+/* DMM_PAT_GEOMETRY */
+#define OMAP44XX_CONT_HGHT_SHIFT 24
+#define OMAP44XX_CONT_HGHT_MASK (0x7 << 24)
+#define OMAP44XX_CONT_WDTH_SHIFT 16
+#define OMAP44XX_CONT_WDTH_MASK (0xf << 16)
+#define OMAP44XX_ADDR_RANGE_SHIFT 8
+#define OMAP44XX_ADDR_RANGE_MASK (0x3f << 8)
+#define OMAP44XX_PAGE_SZ_SHIFT 0
+#define OMAP44XX_PAGE_SZ_MASK (0x1f << 0)
+
+/* DMM_PAT_CONFIG */
+#define OMAP44XX_MODE3_SHIFT 3
+#define OMAP44XX_MODE3_MASK (1 << 3)
+#define OMAP44XX_MODE2_SHIFT 2
+#define OMAP44XX_MODE2_MASK (1 << 2)
+#define OMAP44XX_MODE1_SHIFT 1
+#define OMAP44XX_MODE1_MASK (1 << 1)
+#define OMAP44XX_MODE0_SHIFT 0
+#define OMAP44XX_MODE0_MASK (1 << 0)
+
+/* DMM_PAT_VIEW */
+#define OMAP44XX_V7_SHIFT 28
+#define OMAP44XX_V7_MASK (0x3 << 28)
+#define OMAP44XX_V6_SHIFT 24
+#define OMAP44XX_V6_MASK (0x3 << 24)
+#define OMAP44XX_V5_SHIFT 20
+#define OMAP44XX_V5_MASK (0x3 << 20)
+#define OMAP44XX_V4_SHIFT 16
+#define OMAP44XX_V4_MASK (0x3 << 16)
+#define OMAP44XX_V3_SHIFT 12
+#define OMAP44XX_V3_MASK (0x3 << 12)
+#define OMAP44XX_V2_SHIFT 8
+#define OMAP44XX_V2_MASK (0x3 << 8)
+#define OMAP44XX_V1_SHIFT 4
+#define OMAP44XX_V1_MASK (0x3 << 4)
+#define OMAP44XX_V0_SHIFT 0
+#define OMAP44XX_V0_MASK (0x3 << 0)
+
+/* DMM_PAT_VIEW_MAP */
+#define OMAP44XX_ACCESS_PAGE_SHIFT 31
+#define OMAP44XX_ACCESS_PAGE_MASK (1 << 31)
+#define OMAP44XX_CONT_PAGE_SHIFT 24
+#define OMAP44XX_CONT_PAGE_MASK (0xf << 24)
+#define OMAP44XX_ACCESS_32_SHIFT 23
+#define OMAP44XX_ACCESS_32_MASK (1 << 23)
+#define OMAP44XX_CONT_32_SHIFT 16
+#define OMAP44XX_CONT_32_MASK (0xf << 16)
+#define OMAP44XX_ACCESS_16_SHIFT 15
+#define OMAP44XX_ACCESS_16_MASK (1 << 15)
+#define OMAP44XX_CONT_16_SHIFT 8
+#define OMAP44XX_CONT_16_MASK (0xf << 8)
+#define OMAP44XX_ACCESS_8_SHIFT 7
+#define OMAP44XX_ACCESS_8_MASK (1 << 7)
+#define OMAP44XX_CONT_8_SHIFT 0
+#define OMAP44XX_CONT_8_MASK (0xf << 0)
+
+/* DMM_PAT_VIEW_MAP_BASE */
+#define OMAP44XX_BASE_ADDR_SHIFT 31
+#define OMAP44XX_BASE_ADDR_MASK (1 << 31)
+
+/* DMM_PAT_IRQ_EOI */
+#define OMAP44XX_EOI_SHIFT 0
+#define OMAP44XX_EOI_MASK (1 << 0)
+
+/* DMM_PAT_IRQSTATUS_RAW */
+#define OMAP44XX_ERR_LUT_MISS3_SHIFT 31
+#define OMAP44XX_ERR_LUT_MISS3_MASK (1 << 31)
+#define OMAP44XX_ERR_UPD_DATA3_SHIFT 30
+#define OMAP44XX_ERR_UPD_DATA3_MASK (1 << 30)
+#define OMAP44XX_ERR_UPD_CTRL3_SHIFT 29
+#define OMAP44XX_ERR_UPD_CTRL3_MASK (1 << 29)
+#define OMAP44XX_ERR_UPD_AREA3_SHIFT 28
+#define OMAP44XX_ERR_UPD_AREA3_MASK (1 << 28)
+#define OMAP44XX_ERR_INV_DATA3_SHIFT 27
+#define OMAP44XX_ERR_INV_DATA3_MASK (1 << 27)
+#define OMAP44XX_ERR_INV_DSC3_SHIFT 26
+#define OMAP44XX_ERR_INV_DSC3_MASK (1 << 26)
+#define OMAP44XX_FILL_LST3_SHIFT 25
+#define OMAP44XX_FILL_LST3_MASK (1 << 25)
+#define OMAP44XX_FILL_DSC3_SHIFT 24
+#define OMAP44XX_FILL_DSC3_MASK (1 << 24)
+#define OMAP44XX_ERR_LUT_MISS2_SHIFT 23
+#define OMAP44XX_ERR_LUT_MISS2_MASK (1 << 23)
+#define OMAP44XX_ERR_UPD_DATA2_SHIFT 22
+#define OMAP44XX_ERR_UPD_DATA2_MASK (1 << 22)
+#define OMAP44XX_ERR_UPD_CTRL2_SHIFT 21
+#define OMAP44XX_ERR_UPD_CTRL2_MASK (1 << 21)
+#define OMAP44XX_ERR_UPD_AREA2_SHIFT 20
+#define OMAP44XX_ERR_UPD_AREA2_MASK (1 << 20)
+#define OMAP44XX_ERR_INV_DATA2_SHIFT 19
+#define OMAP44XX_ERR_INV_DATA2_MASK (1 << 19)
+#define OMAP44XX_ERR_INV_DSC2_SHIFT 18
+#define OMAP44XX_ERR_INV_DSC2_MASK (1 << 18)
+#define OMAP44XX_FILL_LST2_SHIFT 17
+#define OMAP44XX_FILL_LST2_MASK (1 << 17)
+#define OMAP44XX_FILL_DSC2_SHIFT 16
+#define OMAP44XX_FILL_DSC2_MASK (1 << 16)
+#define OMAP44XX_ERR_LUT_MISS1_SHIFT 15
+#define OMAP44XX_ERR_LUT_MISS1_MASK (1 << 15)
+#define OMAP44XX_ERR_UPD_DATA1_SHIFT 14
+#define OMAP44XX_ERR_UPD_DATA1_MASK (1 << 14)
+#define OMAP44XX_ERR_UPD_CTRL1_SHIFT 13
+#define OMAP44XX_ERR_UPD_CTRL1_MASK (1 << 13)
+#define OMAP44XX_ERR_UPD_AREA1_SHIFT 12
+#define OMAP44XX_ERR_UPD_AREA1_MASK (1 << 12)
+#define OMAP44XX_ERR_INV_DATA1_SHIFT 11
+#define OMAP44XX_ERR_INV_DATA1_MASK (1 << 11)
+#define OMAP44XX_ERR_INV_DSC1_SHIFT 10
+#define OMAP44XX_ERR_INV_DSC1_MASK (1 << 10)
+#define OMAP44XX_FILL_LST1_SHIFT 9
+#define OMAP44XX_FILL_LST1_MASK (1 << 9)
+#define OMAP44XX_FILL_DSC1_SHIFT 8
+#define OMAP44XX_FILL_DSC1_MASK (1 << 8)
+#define OMAP44XX_ERR_LUT_MISS0_SHIFT 7
+#define OMAP44XX_ERR_LUT_MISS0_MASK (1 << 7)
+#define OMAP44XX_ERR_UPD_DATA0_SHIFT 6
+#define OMAP44XX_ERR_UPD_DATA0_MASK (1 << 6)
+#define OMAP44XX_ERR_UPD_CTRL0_SHIFT 5
+#define OMAP44XX_ERR_UPD_CTRL0_MASK (1 << 5)
+#define OMAP44XX_ERR_UPD_AREA0_SHIFT 4
+#define OMAP44XX_ERR_UPD_AREA0_MASK (1 << 4)
+#define OMAP44XX_ERR_INV_DATA0_SHIFT 3
+#define OMAP44XX_ERR_INV_DATA0_MASK (1 << 3)
+#define OMAP44XX_ERR_INV_DSC0_SHIFT 2
+#define OMAP44XX_ERR_INV_DSC0_MASK (1 << 2)
+#define OMAP44XX_FILL_LST0_SHIFT 1
+#define OMAP44XX_FILL_LST0_MASK (1 << 1)
+#define OMAP44XX_FILL_DSC0_SHIFT 0
+#define OMAP44XX_FILL_DSC0_MASK (1 << 0)
+
+/* DMM_PAT_IRQSTATUS */
+
+/* DMM_PAT_IRQENABLE_SET */
+
+/* DMM_PAT_IRQENABLE_CLR */
+
+/* DMM_PAT_STATUS */
+#define OMAP44XX_CNT_SHIFT 16
+#define OMAP44XX_CNT_MASK (0x1ff << 16)
+#define OMAP44XX_ERROR_SHIFT 10
+#define OMAP44XX_ERROR_MASK (0x3f << 10)
+#define OMAP44XX_BYPASSED_SHIFT 7
+#define OMAP44XX_BYPASSED_MASK (1 << 7)
+#define OMAP44XX_LINKED_SHIFT 4
+#define OMAP44XX_LINKED_MASK (1 << 4)
+#define OMAP44XX_DONE_SHIFT 3
+#define OMAP44XX_DONE_MASK (1 << 3)
+#define OMAP44XX_RUN_SHIFT 2
+#define OMAP44XX_RUN_MASK (1 << 2)
+#define OMAP44XX_VALID_SHIFT 1
+#define OMAP44XX_VALID_MASK (1 << 1)
+#define OMAP44XX_READY_SHIFT 0
+#define OMAP44XX_READY_MASK (1 << 0)
+
+/* DMM_PAT_DESCR */
+#define OMAP44XX_ADDR_SHIFT 4
+#define OMAP44XX_ADDR_MASK (0xfffffff << 4)
+
+/* DMM_PAT_AREA */
+#define OMAP44XX_Y1_SHIFT 24
+#define OMAP44XX_Y1_MASK (0x7f << 24)
+#define OMAP44XX_X1_SHIFT 16
+#define OMAP44XX_X1_MASK (0xff << 16)
+#define OMAP44XX_Y0_SHIFT 8
+#define OMAP44XX_Y0_MASK (0x7f << 8)
+#define OMAP44XX_X0_SHIFT 0
+#define OMAP44XX_X0_MASK (0xff << 0)
+
+/* DMM_PAT_CTRL */
+#define OMAP44XX_INITIATOR_SHIFT 28
+#define OMAP44XX_INITIATOR_MASK (0xf << 28)
+#define OMAP44XX_SYNC_SHIFT 16
+#define OMAP44XX_SYNC_MASK (1 << 16)
+#define OMAP44XX_DIRECTION_SHIFT 4
+#define OMAP44XX_DIRECTION_MASK (0x7 << 4)
+#define OMAP44XX_START_SHIFT 0
+#define OMAP44XX_START_MASK (1 << 0)
+
+/* DMM_PAT_DATA */
+
+/* DMM_PEG_HWINFO */
+#define OMAP44XX_PRIO_CNT_SHIFT 0
+#define OMAP44XX_PRIO_CNT_MASK (0x7f << 0)
+
+/* DMM_PEG_PRIO */
+#define OMAP44XX_P7_SHIFT 28
+#define OMAP44XX_P7_MASK (0x7 << 28)
+#define OMAP44XX_P6_SHIFT 24
+#define OMAP44XX_P6_MASK (0x7 << 24)
+#define OMAP44XX_P5_SHIFT 20
+#define OMAP44XX_P5_MASK (0x7 << 20)
+#define OMAP44XX_P4_SHIFT 16
+#define OMAP44XX_P4_MASK (0x7 << 16)
+#define OMAP44XX_P3_SHIFT 12
+#define OMAP44XX_P3_MASK (0x7 << 12)
+#define OMAP44XX_P2_SHIFT 8
+#define OMAP44XX_P2_MASK (0x7 << 8)
+#define OMAP44XX_P1_SHIFT 4
+#define OMAP44XX_P1_MASK (0x7 << 4)
+#define OMAP44XX_P0_SHIFT 0
+#define OMAP44XX_P0_MASK (0x7 << 0)
+
+/* DMM_PEG_PRIO_PAT */
+#define OMAP44XX_W_PAT_SHIFT 3
+#define OMAP44XX_W_PAT_MASK (1 << 3)
+#define OMAP44XX_P_PAT_SHIFT 0
+#define OMAP44XX_P_PAT_MASK (0x7 << 0)
+#endif
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..3567b6f9
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dmm.h
@@ -0,0 +1,164 @@
+/*
+ * 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);
+
+/**
+ * DMM Platform Device Data structure
+ *
+ */
+struct omap_dmm_platform_data {
+ const char *oh_name;
+ void __iomem *base;
+ int irq;
+};
+
+/**
+ * Init function for use in board init file
+ *
+ */
+void omap_dmm_init(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/emif-44xx.h b/arch/arm/mach-omap2/include/mach/emif-44xx.h
new file mode 100644
index 0000000..58a80f2
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/emif-44xx.h
@@ -0,0 +1,526 @@
+/*
+ * OMAP44xx EMIF registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * 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_EMIF_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_EMIF_44XX_H
+
+
+/* Base address */
+#define OMAP44XX_EMIF1 0x4c000000
+#define OMAP44XX_EMIF2 0x4d000000
+
+/* Registers offset */
+#define OMAP44XX_EMIF_MOD_ID_REV 0x0000
+#define OMAP44XX_EMIF_STATUS 0x0004
+#define OMAP44XX_EMIF_SDRAM_CONFIG 0x0008
+#define OMAP44XX_EMIF_SDRAM_CONFIG_2 0x000c
+#define OMAP44XX_EMIF_SDRAM_REF_CTRL 0x0010
+#define OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW 0x0014
+#define OMAP44XX_EMIF_SDRAM_TIM_1 0x0018
+#define OMAP44XX_EMIF_SDRAM_TIM_1_SHDW 0x001c
+#define OMAP44XX_EMIF_SDRAM_TIM_2 0x0020
+#define OMAP44XX_EMIF_SDRAM_TIM_2_SHDW 0x0024
+#define OMAP44XX_EMIF_SDRAM_TIM_3 0x0028
+#define OMAP44XX_EMIF_SDRAM_TIM_3_SHDW 0x002c
+#define OMAP44XX_EMIF_LPDDR2_NVM_TIM 0x0030
+#define OMAP44XX_EMIF_LPDDR2_NVM_TIM_SHDW 0x0034
+#define OMAP44XX_EMIF_PWR_MGMT_CTRL 0x0038
+#define OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW 0x003c
+#define OMAP44XX_EMIF_LPDDR2_MODE_REG_DATA 0x0040
+#define OMAP44XX_EMIF_LPDDR2_MODE_REG_CFG 0x0050
+#define OMAP44XX_EMIF_OCP_CONFIG 0x0054
+#define OMAP44XX_EMIF_OCP_CFG_VAL_1 0x0058
+#define OMAP44XX_EMIF_OCP_CFG_VAL_2 0x005c
+#define OMAP44XX_EMIF_IODFT_TLGC 0x0060
+#define OMAP44XX_EMIF_IODFT_CTRL_MISR_RSLT 0x0064
+#define OMAP44XX_EMIF_IODFT_ADDR_MISR_RSLT 0x0068
+#define OMAP44XX_EMIF_IODFT_DATA_MISR_RSLT_1 0x006c
+#define OMAP44XX_EMIF_IODFT_DATA_MISR_RSLT_2 0x0070
+#define OMAP44XX_EMIF_IODFT_DATA_MISR_RSLT_3 0x0074
+#define OMAP44XX_EMIF_PERF_CNT_1 0x0080
+#define OMAP44XX_EMIF_PERF_CNT_2 0x0084
+#define OMAP44XX_EMIF_PERF_CNT_CFG 0x0088
+#define OMAP44XX_EMIF_PERF_CNT_SEL 0x008c
+#define OMAP44XX_EMIF_PERF_CNT_TIM 0x0090
+#define OMAP44XX_EMIF_READ_IDLE_CTRL 0x0098
+#define OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW 0x009c
+#define OMAP44XX_EMIF_IRQ_EOI 0x00a0
+#define OMAP44XX_EMIF_IRQSTATUS_RAW_SYS 0x00a4
+#define OMAP44XX_EMIF_IRQSTATUS_RAW_LL 0x00a8
+#define OMAP44XX_EMIF_IRQSTATUS_SYS 0x00ac
+#define OMAP44XX_EMIF_IRQSTATUS_LL 0x00b0
+#define OMAP44XX_EMIF_IRQENABLE_SET_SYS 0x00b4
+#define OMAP44XX_EMIF_IRQENABLE_SET_LL 0x00b8
+#define OMAP44XX_EMIF_IRQENABLE_CLR_SYS 0x00bc
+#define OMAP44XX_EMIF_IRQENABLE_CLR_LL 0x00c0
+#define OMAP44XX_EMIF_ZQ_CONFIG 0x00c8
+#define OMAP44XX_EMIF_TEMP_ALERT_CONFIG 0x00cc
+#define OMAP44XX_EMIF_OCP_ERR_LOG 0x00d0
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1 0x00e4
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_2 0x00ec
+
+/* Registers shifts and masks */
+
+/* EMIF_MOD_ID_REV */
+#define OMAP44XX_REG_SCHEME_SHIFT 30
+#define OMAP44XX_REG_SCHEME_MASK (0x3 << 30)
+#define OMAP44XX_REG_MODULE_ID_SHIFT 16
+#define OMAP44XX_REG_MODULE_ID_MASK (0xfff << 16)
+#define OMAP44XX_REG_RTL_VERSION_SHIFT 11
+#define OMAP44XX_REG_RTL_VERSION_MASK (0x1f << 11)
+#define OMAP44XX_REG_MAJOR_REVISION_SHIFT 8
+#define OMAP44XX_REG_MAJOR_REVISION_MASK (0x7 << 8)
+#define OMAP44XX_REG_MINOR_REVISION_SHIFT 0
+#define OMAP44XX_REG_MINOR_REVISION_MASK (0x3f << 0)
+
+/* STATUS */
+#define OMAP44XX_REG_BE_SHIFT 31
+#define OMAP44XX_REG_BE_MASK (1 << 31)
+#define OMAP44XX_REG_DUAL_CLK_MODE_SHIFT 30
+#define OMAP44XX_REG_DUAL_CLK_MODE_MASK (1 << 30)
+#define OMAP44XX_REG_FAST_INIT_SHIFT 29
+#define OMAP44XX_REG_FAST_INIT_MASK (1 << 29)
+#define OMAP44XX_REG_PHY_DLL_READY_SHIFT 2
+#define OMAP44XX_REG_PHY_DLL_READY_MASK (1 << 2)
+
+/* SDRAM_CONFIG */
+#define OMAP44XX_REG_SDRAM_TYPE_SHIFT 29
+#define OMAP44XX_REG_SDRAM_TYPE_MASK (0x7 << 29)
+#define OMAP44XX_REG_IBANK_POS_SHIFT 27
+#define OMAP44XX_REG_IBANK_POS_MASK (0x3 << 27)
+#define OMAP44XX_REG_DDR_TERM_SHIFT 24
+#define OMAP44XX_REG_DDR_TERM_MASK (0x7 << 24)
+#define OMAP44XX_REG_DDR2_DDQS_SHIFT 23
+#define OMAP44XX_REG_DDR2_DDQS_MASK (1 << 23)
+#define OMAP44XX_REG_DYN_ODT_SHIFT 21
+#define OMAP44XX_REG_DYN_ODT_MASK (0x3 << 21)
+#define OMAP44XX_REG_DDR_DISABLE_DLL_SHIFT 20
+#define OMAP44XX_REG_DDR_DISABLE_DLL_MASK (1 << 20)
+#define OMAP44XX_REG_SDRAM_DRIVE_SHIFT 18
+#define OMAP44XX_REG_SDRAM_DRIVE_MASK (0x3 << 18)
+#define OMAP44XX_REG_CWL_SHIFT 16
+#define OMAP44XX_REG_CWL_MASK (0x3 << 16)
+#define OMAP44XX_REG_NARROW_MODE_SHIFT 14
+#define OMAP44XX_REG_NARROW_MODE_MASK (0x3 << 14)
+#define OMAP44XX_REG_CL_SHIFT 10
+#define OMAP44XX_REG_CL_MASK (0xf << 10)
+#define OMAP44XX_REG_ROWSIZE_SHIFT 7
+#define OMAP44XX_REG_ROWSIZE_MASK (0x7 << 7)
+#define OMAP44XX_REG_IBANK_SHIFT 4
+#define OMAP44XX_REG_IBANK_MASK (0x7 << 4)
+#define OMAP44XX_REG_EBANK_SHIFT 3
+#define OMAP44XX_REG_EBANK_MASK (1 << 3)
+#define OMAP44XX_REG_PAGESIZE_SHIFT 0
+#define OMAP44XX_REG_PAGESIZE_MASK (0x7 << 0)
+
+/* SDRAM_CONFIG_2 */
+#define OMAP44XX_REG_CS1NVMEN_SHIFT 30
+#define OMAP44XX_REG_CS1NVMEN_MASK (1 << 30)
+#define OMAP44XX_REG_EBANK_POS_SHIFT 27
+#define OMAP44XX_REG_EBANK_POS_MASK (1 << 27)
+#define OMAP44XX_REG_RDBNUM_SHIFT 4
+#define OMAP44XX_REG_RDBNUM_MASK (0x3 << 4)
+#define OMAP44XX_REG_RDBSIZE_SHIFT 0
+#define OMAP44XX_REG_RDBSIZE_MASK (0x7 << 0)
+
+/* SDRAM_REF_CTRL */
+#define OMAP44XX_REG_INITREF_DIS_SHIFT 31
+#define OMAP44XX_REG_INITREF_DIS_MASK (1 << 31)
+#define OMAP44XX_REG_SRT_SHIFT 29
+#define OMAP44XX_REG_SRT_MASK (1 << 29)
+#define OMAP44XX_REG_ASR_SHIFT 28
+#define OMAP44XX_REG_ASR_MASK (1 << 28)
+#define OMAP44XX_REG_PASR_SHIFT 24
+#define OMAP44XX_REG_PASR_MASK (0x7 << 24)
+#define OMAP44XX_REG_REFRESH_RATE_SHIFT 0
+#define OMAP44XX_REG_REFRESH_RATE_MASK (0xffff << 0)
+
+/* SDRAM_REF_CTRL_SHDW */
+#define OMAP44XX_REG_REFRESH_RATE_SHDW_SHIFT 0
+#define OMAP44XX_REG_REFRESH_RATE_SHDW_MASK (0xffff << 0)
+
+/* SDRAM_TIM_1 */
+#define OMAP44XX_REG_T_RP_SHIFT 25
+#define OMAP44XX_REG_T_RP_MASK (0xf << 25)
+#define OMAP44XX_REG_T_RCD_SHIFT 21
+#define OMAP44XX_REG_T_RCD_MASK (0xf << 21)
+#define OMAP44XX_REG_T_WR_SHIFT 17
+#define OMAP44XX_REG_T_WR_MASK (0xf << 17)
+#define OMAP44XX_REG_T_RAS_SHIFT 12
+#define OMAP44XX_REG_T_RAS_MASK (0x1f << 12)
+#define OMAP44XX_REG_T_RC_SHIFT 6
+#define OMAP44XX_REG_T_RC_MASK (0x3f << 6)
+#define OMAP44XX_REG_T_RRD_SHIFT 3
+#define OMAP44XX_REG_T_RRD_MASK (0x7 << 3)
+#define OMAP44XX_REG_T_WTR_SHIFT 0
+#define OMAP44XX_REG_T_WTR_MASK (0x7 << 0)
+
+/* SDRAM_TIM_1_SHDW */
+#define OMAP44XX_REG_T_RP_SHDW_SHIFT 25
+#define OMAP44XX_REG_T_RP_SHDW_MASK (0xf << 25)
+#define OMAP44XX_REG_T_RCD_SHDW_SHIFT 21
+#define OMAP44XX_REG_T_RCD_SHDW_MASK (0xf << 21)
+#define OMAP44XX_REG_T_WR_SHDW_SHIFT 17
+#define OMAP44XX_REG_T_WR_SHDW_MASK (0xf << 17)
+#define OMAP44XX_REG_T_RAS_SHDW_SHIFT 12
+#define OMAP44XX_REG_T_RAS_SHDW_MASK (0x1f << 12)
+#define OMAP44XX_REG_T_RC_SHDW_SHIFT 6
+#define OMAP44XX_REG_T_RC_SHDW_MASK (0x3f << 6)
+#define OMAP44XX_REG_T_RRD_SHDW_SHIFT 3
+#define OMAP44XX_REG_T_RRD_SHDW_MASK (0x7 << 3)
+#define OMAP44XX_REG_T_WTR_SHDW_SHIFT 0
+#define OMAP44XX_REG_T_WTR_SHDW_MASK (0x7 << 0)
+
+/* SDRAM_TIM_2 */
+#define OMAP44XX_REG_T_XP_SHIFT 28
+#define OMAP44XX_REG_T_XP_MASK (0x7 << 28)
+#define OMAP44XX_REG_T_ODT_SHIFT 25
+#define OMAP44XX_REG_T_ODT_MASK (0x7 << 25)
+#define OMAP44XX_REG_T_XSNR_SHIFT 16
+#define OMAP44XX_REG_T_XSNR_MASK (0x1ff << 16)
+#define OMAP44XX_REG_T_XSRD_SHIFT 6
+#define OMAP44XX_REG_T_XSRD_MASK (0x3ff << 6)
+#define OMAP44XX_REG_T_RTP_SHIFT 3
+#define OMAP44XX_REG_T_RTP_MASK (0x7 << 3)
+#define OMAP44XX_REG_T_CKE_SHIFT 0
+#define OMAP44XX_REG_T_CKE_MASK (0x7 << 0)
+
+/* SDRAM_TIM_2_SHDW */
+#define OMAP44XX_REG_T_XP_SHDW_SHIFT 28
+#define OMAP44XX_REG_T_XP_SHDW_MASK (0x7 << 28)
+#define OMAP44XX_REG_T_ODT_SHDW_SHIFT 25
+#define OMAP44XX_REG_T_ODT_SHDW_MASK (0x7 << 25)
+#define OMAP44XX_REG_T_XSNR_SHDW_SHIFT 16
+#define OMAP44XX_REG_T_XSNR_SHDW_MASK (0x1ff << 16)
+#define OMAP44XX_REG_T_XSRD_SHDW_SHIFT 6
+#define OMAP44XX_REG_T_XSRD_SHDW_MASK (0x3ff << 6)
+#define OMAP44XX_REG_T_RTP_SHDW_SHIFT 3
+#define OMAP44XX_REG_T_RTP_SHDW_MASK (0x7 << 3)
+#define OMAP44XX_REG_T_CKE_SHDW_SHIFT 0
+#define OMAP44XX_REG_T_CKE_SHDW_MASK (0x7 << 0)
+
+/* SDRAM_TIM_3 */
+#define OMAP44XX_REG_T_CKESR_SHIFT 21
+#define OMAP44XX_REG_T_CKESR_MASK (0x7 << 21)
+#define OMAP44XX_REG_ZQ_ZQCS_SHIFT 15
+#define OMAP44XX_REG_ZQ_ZQCS_MASK (0x3f << 15)
+#define OMAP44XX_REG_T_TDQSCKMAX_SHIFT 13
+#define OMAP44XX_REG_T_TDQSCKMAX_MASK (0x3 << 13)
+#define OMAP44XX_REG_T_RFC_SHIFT 4
+#define OMAP44XX_REG_T_RFC_MASK (0x1ff << 4)
+#define OMAP44XX_REG_T_RAS_MAX_SHIFT 0
+#define OMAP44XX_REG_T_RAS_MAX_MASK (0xf << 0)
+
+/* SDRAM_TIM_3_SHDW */
+#define OMAP44XX_REG_T_CKESR_SHDW_SHIFT 21
+#define OMAP44XX_REG_T_CKESR_SHDW_MASK (0x7 << 21)
+#define OMAP44XX_REG_ZQ_ZQCS_SHDW_SHIFT 15
+#define OMAP44XX_REG_ZQ_ZQCS_SHDW_MASK (0x3f << 15)
+#define OMAP44XX_REG_T_TDQSCKMAX_SHDW_SHIFT 13
+#define OMAP44XX_REG_T_TDQSCKMAX_SHDW_MASK (0x3 << 13)
+#define OMAP44XX_REG_T_RFC_SHDW_SHIFT 4
+#define OMAP44XX_REG_T_RFC_SHDW_MASK (0x1ff << 4)
+#define OMAP44XX_REG_T_RAS_MAX_SHDW_SHIFT 0
+#define OMAP44XX_REG_T_RAS_MAX_SHDW_MASK (0xf << 0)
+
+/* LPDDR2_NVM_TIM */
+#define OMAP44XX_REG_NVM_T_XP_SHIFT 28
+#define OMAP44XX_REG_NVM_T_XP_MASK (0x7 << 28)
+#define OMAP44XX_REG_NVM_T_WTR_SHIFT 24
+#define OMAP44XX_REG_NVM_T_WTR_MASK (0x7 << 24)
+#define OMAP44XX_REG_NVM_T_RP_SHIFT 20
+#define OMAP44XX_REG_NVM_T_RP_MASK (0xf << 20)
+#define OMAP44XX_REG_NVM_T_WRA_SHIFT 16
+#define OMAP44XX_REG_NVM_T_WRA_MASK (0xf << 16)
+#define OMAP44XX_REG_NVM_T_RRD_SHIFT 8
+#define OMAP44XX_REG_NVM_T_RRD_MASK (0xff << 8)
+#define OMAP44XX_REG_NVM_T_RCDMIN_SHIFT 0
+#define OMAP44XX_REG_NVM_T_RCDMIN_MASK (0xff << 0)
+
+/* LPDDR2_NVM_TIM_SHDW */
+#define OMAP44XX_REG_NVM_T_XP_SHDW_SHIFT 28
+#define OMAP44XX_REG_NVM_T_XP_SHDW_MASK (0x7 << 28)
+#define OMAP44XX_REG_NVM_T_WTR_SHDW_SHIFT 24
+#define OMAP44XX_REG_NVM_T_WTR_SHDW_MASK (0x7 << 24)
+#define OMAP44XX_REG_NVM_T_RP_SHDW_SHIFT 20
+#define OMAP44XX_REG_NVM_T_RP_SHDW_MASK (0xf << 20)
+#define OMAP44XX_REG_NVM_T_WRA_SHDW_SHIFT 16
+#define OMAP44XX_REG_NVM_T_WRA_SHDW_MASK (0xf << 16)
+#define OMAP44XX_REG_NVM_T_RRD_SHDW_SHIFT 8
+#define OMAP44XX_REG_NVM_T_RRD_SHDW_MASK (0xff << 8)
+#define OMAP44XX_REG_NVM_T_RCDMIN_SHDW_SHIFT 0
+#define OMAP44XX_REG_NVM_T_RCDMIN_SHDW_MASK (0xff << 0)
+
+/* PWR_MGMT_CTRL */
+#define OMAP44XX_REG_PD_TIM_SHIFT 12
+#define OMAP44XX_REG_PD_TIM_MASK (0xf << 12)
+#define OMAP44XX_REG_DPD_EN_SHIFT 11
+#define OMAP44XX_REG_DPD_EN_MASK (1 << 11)
+#define OMAP44XX_REG_LP_MODE_SHIFT 8
+#define OMAP44XX_REG_LP_MODE_MASK (0x7 << 8)
+#define OMAP44XX_REG_SR_TIM_SHIFT 4
+#define OMAP44XX_REG_SR_TIM_MASK (0xf << 4)
+#define OMAP44XX_REG_CS_TIM_SHIFT 0
+#define OMAP44XX_REG_CS_TIM_MASK (0xf << 0)
+
+/* PWR_MGMT_CTRL_SHDW */
+#define OMAP44XX_REG_PD_TIM_SHDW_SHIFT 12
+#define OMAP44XX_REG_PD_TIM_SHDW_MASK (0xf << 12)
+#define OMAP44XX_REG_SR_TIM_SHDW_SHIFT 4
+#define OMAP44XX_REG_SR_TIM_SHDW_MASK (0xf << 4)
+#define OMAP44XX_REG_CS_TIM_SHDW_SHIFT 0
+#define OMAP44XX_REG_CS_TIM_SHDW_MASK (0xf << 0)
+
+/* LPDDR2_MODE_REG_DATA */
+#define OMAP44XX_REG_VALUE_0_SHIFT 0
+#define OMAP44XX_REG_VALUE_0_MASK (0x7f << 0)
+
+/* LPDDR2_MODE_REG_CFG */
+#define OMAP44XX_REG_CS_SHIFT 31
+#define OMAP44XX_REG_CS_MASK (1 << 31)
+#define OMAP44XX_REG_REFRESH_EN_SHIFT 30
+#define OMAP44XX_REG_REFRESH_EN_MASK (1 << 30)
+#define OMAP44XX_REG_ADDRESS_SHIFT 0
+#define OMAP44XX_REG_ADDRESS_MASK (0xff << 0)
+
+/* OCP_CONFIG */
+#define OMAP44XX_REG_SYS_THRESH_MAX_SHIFT 24
+#define OMAP44XX_REG_SYS_THRESH_MAX_MASK (0xf << 24)
+#define OMAP44XX_REG_LL_THRESH_MAX_SHIFT 16
+#define OMAP44XX_REG_LL_THRESH_MAX_MASK (0xf << 16)
+#define OMAP44XX_REG_PR_OLD_COUNT_SHIFT 0
+#define OMAP44XX_REG_PR_OLD_COUNT_MASK (0xff << 0)
+
+/* OCP_CFG_VAL_1 */
+#define OMAP44XX_REG_SYS_BUS_WIDTH_SHIFT 30
+#define OMAP44XX_REG_SYS_BUS_WIDTH_MASK (0x3 << 30)
+#define OMAP44XX_REG_LL_BUS_WIDTH_SHIFT 28
+#define OMAP44XX_REG_LL_BUS_WIDTH_MASK (0x3 << 28)
+#define OMAP44XX_REG_WR_FIFO_DEPTH_SHIFT 8
+#define OMAP44XX_REG_WR_FIFO_DEPTH_MASK (0xff << 8)
+#define OMAP44XX_REG_CMD_FIFO_DEPTH_SHIFT 0
+#define OMAP44XX_REG_CMD_FIFO_DEPTH_MASK (0xff << 0)
+
+/* OCP_CFG_VAL_2 */
+#define OMAP44XX_REG_RREG_FIFO_DEPTH_SHIFT 16
+#define OMAP44XX_REG_RREG_FIFO_DEPTH_MASK (0xff << 16)
+#define OMAP44XX_REG_RSD_FIFO_DEPTH_SHIFT 8
+#define OMAP44XX_REG_RSD_FIFO_DEPTH_MASK (0xff << 8)
+#define OMAP44XX_REG_RCMD_FIFO_DEPTH_SHIFT 0
+#define OMAP44XX_REG_RCMD_FIFO_DEPTH_MASK (0xff << 0)
+
+/* IODFT_TLGC */
+#define OMAP44XX_REG_TLEC_SHIFT 16
+#define OMAP44XX_REG_TLEC_MASK (0xffff << 16)
+#define OMAP44XX_REG_MT_SHIFT 14
+#define OMAP44XX_REG_MT_MASK (1 << 14)
+#define OMAP44XX_REG_ACT_CAP_EN_SHIFT 13
+#define OMAP44XX_REG_ACT_CAP_EN_MASK (1 << 13)
+#define OMAP44XX_REG_OPG_LD_SHIFT 12
+#define OMAP44XX_REG_OPG_LD_MASK (1 << 12)
+#define OMAP44XX_REG_RESET_PHY_SHIFT 10
+#define OMAP44XX_REG_RESET_PHY_MASK (1 << 10)
+#define OMAP44XX_REG_MMS_SHIFT 8
+#define OMAP44XX_REG_MMS_MASK (1 << 8)
+#define OMAP44XX_REG_MC_SHIFT 4
+#define OMAP44XX_REG_MC_MASK (0x3 << 4)
+#define OMAP44XX_REG_PC_SHIFT 1
+#define OMAP44XX_REG_PC_MASK (0x7 << 1)
+#define OMAP44XX_REG_TM_SHIFT 0
+#define OMAP44XX_REG_TM_MASK (1 << 0)
+
+/* IODFT_CTRL_MISR_RSLT */
+#define OMAP44XX_REG_DQM_TLMR_SHIFT 16
+#define OMAP44XX_REG_DQM_TLMR_MASK (0x3ff << 16)
+#define OMAP44XX_REG_CTL_TLMR_SHIFT 0
+#define OMAP44XX_REG_CTL_TLMR_MASK (0x7ff << 0)
+
+/* IODFT_ADDR_MISR_RSLT */
+#define OMAP44XX_REG_ADDR_TLMR_SHIFT 0
+#define OMAP44XX_REG_ADDR_TLMR_MASK (0x1fffff << 0)
+
+/* IODFT_DATA_MISR_RSLT_1 */
+#define OMAP44XX_REG_DATA_TLMR_31_0_SHIFT 0
+#define OMAP44XX_REG_DATA_TLMR_31_0_MASK (0xffffffff << 0)
+
+/* IODFT_DATA_MISR_RSLT_2 */
+#define OMAP44XX_REG_DATA_TLMR_63_32_SHIFT 0
+#define OMAP44XX_REG_DATA_TLMR_63_32_MASK (0xffffffff << 0)
+
+/* IODFT_DATA_MISR_RSLT_3 */
+#define OMAP44XX_REG_DATA_TLMR_66_64_SHIFT 0
+#define OMAP44XX_REG_DATA_TLMR_66_64_MASK (0x7 << 0)
+
+/* PERF_CNT_1 */
+#define OMAP44XX_REG_COUNTER1_SHIFT 0
+#define OMAP44XX_REG_COUNTER1_MASK (0xffffffff << 0)
+
+/* PERF_CNT_2 */
+#define OMAP44XX_REG_COUNTER2_SHIFT 0
+#define OMAP44XX_REG_COUNTER2_MASK (0xffffffff << 0)
+
+/* PERF_CNT_CFG */
+#define OMAP44XX_REG_CNTR2_MCONNID_EN_SHIFT 31
+#define OMAP44XX_REG_CNTR2_MCONNID_EN_MASK (1 << 31)
+#define OMAP44XX_REG_CNTR2_REGION_EN_SHIFT 30
+#define OMAP44XX_REG_CNTR2_REGION_EN_MASK (1 << 30)
+#define OMAP44XX_REG_CNTR2_CFG_SHIFT 16
+#define OMAP44XX_REG_CNTR2_CFG_MASK (0xf << 16)
+#define OMAP44XX_REG_CNTR1_MCONNID_EN_SHIFT 15
+#define OMAP44XX_REG_CNTR1_MCONNID_EN_MASK (1 << 15)
+#define OMAP44XX_REG_CNTR1_REGION_EN_SHIFT 14
+#define OMAP44XX_REG_CNTR1_REGION_EN_MASK (1 << 14)
+#define OMAP44XX_REG_CNTR1_CFG_SHIFT 0
+#define OMAP44XX_REG_CNTR1_CFG_MASK (0xf << 0)
+
+/* PERF_CNT_SEL */
+#define OMAP44XX_REG_MCONNID2_SHIFT 24
+#define OMAP44XX_REG_MCONNID2_MASK (0xff << 24)
+#define OMAP44XX_REG_REGION_SEL2_SHIFT 16
+#define OMAP44XX_REG_REGION_SEL2_MASK (0x3 << 16)
+#define OMAP44XX_REG_MCONNID1_SHIFT 8
+#define OMAP44XX_REG_MCONNID1_MASK (0xff << 8)
+#define OMAP44XX_REG_REGION_SEL1_SHIFT 0
+#define OMAP44XX_REG_REGION_SEL1_MASK (0x3 << 0)
+
+/* PERF_CNT_TIM */
+#define OMAP44XX_REG_TOTAL_TIME_SHIFT 0
+#define OMAP44XX_REG_TOTAL_TIME_MASK (0xffffffff << 0)
+
+/* READ_IDLE_CTRL */
+#define OMAP44XX_REG_READ_IDLE_LEN_SHIFT 16
+#define OMAP44XX_REG_READ_IDLE_LEN_MASK (0xf << 16)
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_SHIFT 0
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_MASK (0x1ff << 0)
+
+/* READ_IDLE_CTRL_SHDW */
+#define OMAP44XX_REG_READ_IDLE_LEN_SHDW_SHIFT 16
+#define OMAP44XX_REG_READ_IDLE_LEN_SHDW_MASK (0xf << 16)
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_SHDW_SHIFT 0
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_SHDW_MASK (0x1ff << 0)
+
+/* IRQ_EOI */
+#define OMAP44XX_REG_EOI_SHIFT 0
+#define OMAP44XX_REG_EOI_MASK (1 << 0)
+
+/* IRQSTATUS_RAW_SYS */
+#define OMAP44XX_REG_DNV_SYS_SHIFT 2
+#define OMAP44XX_REG_DNV_SYS_MASK (1 << 2)
+#define OMAP44XX_REG_TA_SYS_SHIFT 1
+#define OMAP44XX_REG_TA_SYS_MASK (1 << 1)
+#define OMAP44XX_REG_ERR_SYS_SHIFT 0
+#define OMAP44XX_REG_ERR_SYS_MASK (1 << 0)
+
+/* IRQSTATUS_RAW_LL */
+#define OMAP44XX_REG_DNV_LL_SHIFT 2
+#define OMAP44XX_REG_DNV_LL_MASK (1 << 2)
+#define OMAP44XX_REG_TA_LL_SHIFT 1
+#define OMAP44XX_REG_TA_LL_MASK (1 << 1)
+#define OMAP44XX_REG_ERR_LL_SHIFT 0
+#define OMAP44XX_REG_ERR_LL_MASK (1 << 0)
+
+/* IRQSTATUS_SYS */
+
+/* IRQSTATUS_LL */
+
+/* IRQENABLE_SET_SYS */
+#define OMAP44XX_REG_EN_DNV_SYS_SHIFT 2
+#define OMAP44XX_REG_EN_DNV_SYS_MASK (1 << 2)
+#define OMAP44XX_REG_EN_TA_SYS_SHIFT 1
+#define OMAP44XX_REG_EN_TA_SYS_MASK (1 << 1)
+#define OMAP44XX_REG_EN_ERR_SYS_SHIFT 0
+#define OMAP44XX_REG_EN_ERR_SYS_MASK (1 << 0)
+
+/* IRQENABLE_SET_LL */
+#define OMAP44XX_REG_EN_DNV_LL_SHIFT 2
+#define OMAP44XX_REG_EN_DNV_LL_MASK (1 << 2)
+#define OMAP44XX_REG_EN_TA_LL_SHIFT 1
+#define OMAP44XX_REG_EN_TA_LL_MASK (1 << 1)
+#define OMAP44XX_REG_EN_ERR_LL_SHIFT 0
+#define OMAP44XX_REG_EN_ERR_LL_MASK (1 << 0)
+
+/* IRQENABLE_CLR_SYS */
+
+/* IRQENABLE_CLR_LL */
+
+/* ZQ_CONFIG */
+#define OMAP44XX_REG_ZQ_CS1EN_SHIFT 31
+#define OMAP44XX_REG_ZQ_CS1EN_MASK (1 << 31)
+#define OMAP44XX_REG_ZQ_CS0EN_SHIFT 30
+#define OMAP44XX_REG_ZQ_CS0EN_MASK (1 << 30)
+#define OMAP44XX_REG_ZQ_DUALCALEN_SHIFT 29
+#define OMAP44XX_REG_ZQ_DUALCALEN_MASK (1 << 29)
+#define OMAP44XX_REG_ZQ_SFEXITEN_SHIFT 28
+#define OMAP44XX_REG_ZQ_SFEXITEN_MASK (1 << 28)
+#define OMAP44XX_REG_ZQ_ZQINIT_MULT_SHIFT 18
+#define OMAP44XX_REG_ZQ_ZQINIT_MULT_MASK (0x3 << 18)
+#define OMAP44XX_REG_ZQ_ZQCL_MULT_SHIFT 16
+#define OMAP44XX_REG_ZQ_ZQCL_MULT_MASK (0x3 << 16)
+#define OMAP44XX_REG_ZQ_REFINTERVAL_SHIFT 0
+#define OMAP44XX_REG_ZQ_REFINTERVAL_MASK (0xffff << 0)
+
+/* TEMP_ALERT_CONFIG */
+#define OMAP44XX_REG_TA_CS1EN_SHIFT 31
+#define OMAP44XX_REG_TA_CS1EN_MASK (1 << 31)
+#define OMAP44XX_REG_TA_CS0EN_SHIFT 30
+#define OMAP44XX_REG_TA_CS0EN_MASK (1 << 30)
+#define OMAP44XX_REG_TA_SFEXITEN_SHIFT 28
+#define OMAP44XX_REG_TA_SFEXITEN_MASK (1 << 28)
+#define OMAP44XX_REG_TA_DEVWDT_SHIFT 26
+#define OMAP44XX_REG_TA_DEVWDT_MASK (0x3 << 26)
+#define OMAP44XX_REG_TA_DEVCNT_SHIFT 24
+#define OMAP44XX_REG_TA_DEVCNT_MASK (0x3 << 24)
+#define OMAP44XX_REG_TA_REFINTERVAL_SHIFT 0
+#define OMAP44XX_REG_TA_REFINTERVAL_MASK (0x3fffff << 0)
+
+/* OCP_ERR_LOG */
+#define OMAP44XX_REG_MADDRSPACE_SHIFT 14
+#define OMAP44XX_REG_MADDRSPACE_MASK (0x3 << 14)
+#define OMAP44XX_REG_MBURSTSEQ_SHIFT 11
+#define OMAP44XX_REG_MBURSTSEQ_MASK (0x7 << 11)
+#define OMAP44XX_REG_MCMD_SHIFT 8
+#define OMAP44XX_REG_MCMD_MASK (0x7 << 8)
+#define OMAP44XX_REG_MCONNID_SHIFT 0
+#define OMAP44XX_REG_MCONNID_MASK (0xff << 0)
+
+/* DDR_PHY_CTRL_1 */
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_SHIFT 4
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_MASK (0xfffffff << 4)
+#define OMAP44XX_REG_READ_LATENCY_SHIFT 0
+#define OMAP44XX_REG_READ_LATENCY_MASK (0xf << 0)
+#define OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_SHIFT 4
+#define OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_MASK (0xFF << 4)
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_SHIFT 12
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_MASK (0xFFFFF << 12)
+
+/* DDR_PHY_CTRL_1_SHDW */
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_SHDW_SHIFT 4
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_SHDW_MASK (0xfffffff << 4)
+#define OMAP44XX_REG_READ_LATENCY_SHDW_SHIFT 0
+#define OMAP44XX_REG_READ_LATENCY_SHDW_MASK (0xf << 0)
+#define OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_SHDW_SHIFT 4
+#define OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_SHDW_MASK (0xFF << 4)
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_SHDW_SHIFT 12
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_SHDW_MASK (0xFFFFF << 12)
+
+/* DDR_PHY_CTRL_2 */
+#define OMAP44XX_REG_DDR_PHY_CTRL_2_SHIFT 0
+#define OMAP44XX_REG_DDR_PHY_CTRL_2_MASK (0xffffffff << 0)
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/emif.h b/arch/arm/mach-omap2/include/mach/emif.h
new file mode 100644
index 0000000..8a3ea34
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/emif.h
@@ -0,0 +1,268 @@
+/*
+ * OMAP44xx EMIF header
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 _EMIF_H
+#define _EMIF_H
+
+#include <mach/emif-44xx.h>
+#include <mach/lpddr2-jedec.h>
+
+#define EMIF_NUM_INSTANCES 2
+#define EMIF1 0
+#define EMIF2 1
+
+/* The maximum frequency at which the LPDDR2 interface can operate in Hz*/
+#define MAX_LPDDR2_FREQ 400000000 /* 400 MHz */
+
+/* 19.2 MHz to be used for finding initialization values */
+#define EMIF_FREQ_19_2_MHZ 19200000 /* 19.2 MHz */
+/*
+ * The period of DDR clk is represented as numerator and denominator for
+ * better accuracy in integer based calculations. However, if the numerator
+ * and denominator are very huge there may be chances of overflow in
+ * calculations. So, as a trade-off keep denominator(and consequently
+ * numerator) within a limit sacrificing some accuracy - but not much
+ * If denominator and numerator are already small (such as at 400 MHz)
+ * no adjustment is needed
+ */
+#define EMIF_PERIOD_DEN_LIMIT 1000
+/*
+ * Maximum number of different frequencies supported by EMIF driver
+ * Determines the number of entries in the pointer array for register
+ * cache
+ */
+#define EMIF_MAX_NUM_FREQUENCIES 6
+/*
+ * Indices into the Addressing Table array.
+ * One entry each for all the different types of devices with different
+ * addressing schemes
+ */
+#define ADDR_TABLE_INDEX64M 0
+#define ADDR_TABLE_INDEX128M 1
+#define ADDR_TABLE_INDEX256M 2
+#define ADDR_TABLE_INDEX512M 3
+#define ADDR_TABLE_INDEX1GS4 4
+#define ADDR_TABLE_INDEX2GS4 5
+#define ADDR_TABLE_INDEX4G 6
+#define ADDR_TABLE_INDEX8G 7
+#define ADDR_TABLE_INDEX1GS2 8
+#define ADDR_TABLE_INDEX2GS2 9
+#define ADDR_TABLE_INDEXMAX 10
+
+/* Number of Row bits */
+#define ROW_9 0
+#define ROW_10 1
+#define ROW_11 2
+#define ROW_12 3
+#define ROW_13 4
+#define ROW_14 5
+#define ROW_15 6
+#define ROW_16 7
+
+/* Number of Column bits */
+#define COL_8 0
+#define COL_9 1
+#define COL_10 2
+#define COL_11 3
+#define COL_7 4 /*Not supported by OMAP included for completeness */
+
+/* Number of Banks*/
+#define BANKS1 0
+#define BANKS2 1
+#define BANKS4 2
+#define BANKS8 3
+
+/* Refresh rate in micro seconds x 10 */
+#define T_REFI_15_6 156
+#define T_REFI_7_8 78
+#define T_REFI_3_9 39
+
+#define EBANK_CS1_DIS 0
+#define EBANK_CS1_EN 1
+
+/* Read Latency at the base frequency - 19.2 MHz on bootup */
+#define RL_19_2_MHZ 3
+/* Interleaving policies at EMIF level- between banks and Chip Selects */
+#define EMIF_INTERLEAVING_POLICY_MAX_INTERLEAVING 0
+#define EMIF_INTERLEAVING_POLICY_NO_BANK_INTERLEAVING 3
+
+/*
+ * Interleaving policy to be used
+ * Currently set to MAX interleaving for better performance
+ */
+#define EMIF_INTERLEAVING_POLICY EMIF_INTERLEAVING_POLICY_MAX_INTERLEAVING
+
+/* State of the core voltage:
+ * This is important for some parameters such as read idle control and
+ * ZQ calibration timings. Timings are much stricter when voltage ramp
+ * is happening compared to when the voltage is stable.
+ * We need to calculate two sets of values for these parameters and use
+ * them accordingly
+ */
+#define LPDDR2_VOLTAGE_STABLE 0
+#define LPDDR2_VOLTAGE_RAMPING 1
+
+/* Length of the forced read idle period in terms of cycles */
+#define EMIF_REG_READ_IDLE_LEN_VAL 5
+
+/* Interval between forced 'read idles' */
+/* To be used when voltage is changed for DPS/DVFS - 1us */
+#define READ_IDLE_INTERVAL_DVFS (1*1000)
+/*
+ * To be used when voltage is not scaled except by Smart Reflex
+ * 50us - or maximum value will do
+ */
+#define READ_IDLE_INTERVAL_NORMAL (50*1000)
+
+
+/*
+ * Unless voltage is changing due to DVFS one ZQCS command every 50ms should
+ * be enough. This shoule be enough also in the case when voltage is changing
+ * due to smart-reflex.
+ */
+#define EMIF_ZQCS_INTERVAL_NORMAL_IN_US (50*1000)
+/*
+ * If voltage is changing due to DVFS ZQCS should be performed more
+ * often(every 50us)
+ */
+#define EMIF_ZQCS_INTERVAL_DVFS_IN_US 50
+
+/* The interval between ZQCL commands as a multiple of ZQCS interval */
+#define REG_ZQ_ZQCL_MULT 4
+/* The interval between ZQINIT commands as a multiple of ZQCL interval */
+#define REG_ZQ_ZQINIT_MULT 3
+/* Enable ZQ Calibration on exiting Self-refresh */
+#define REG_ZQ_SFEXITEN_ENABLE 1
+/*
+ * ZQ Calibration simultaneously on both chip-selects:
+ * Needs one calibration resistor per CS
+ * None of the boards that we know of have this capability
+ * So disabled by default
+ */
+#define REG_ZQ_DUALCALEN_DISABLE 0
+/*
+ * Enable ZQ Calibration by default on CS0. If we are asked to program
+ * the EMIF there will be something connected to CS0 for sure
+ */
+#define REG_ZQ_CS0EN_ENABLE 1
+
+/* EMIF_PWR_MGMT_CTRL register */
+/* Low power modes */
+#define LP_MODE_DISABLE 0
+#define LP_MODE_CLOCK_STOP 1
+#define LP_MODE_SELF_REFRESH 2
+#define LP_MODE_PWR_DN 3
+
+/* REG_DPD_EN */
+#define DPD_DISABLE 0
+#define DPD_ENABLE 1
+
+/*
+ * Value of bits 12:31 of DDR_PHY_CTRL_1 register:
+ * All these fields have magic values dependent on frequency and
+ * determined by PHY and DLL integration with EMIF. Setting the magic
+ * values suggested by hw team.
+ */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL 0x049FF
+#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ 0x41
+#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ 0x80
+#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS 0xFF
+
+/*
+* MR1 value:
+* Burst length : 8
+* Burst type : sequential
+* Wrap : enabled
+* nWR : 3(default). EMIF does not do pre-charge.
+* : So nWR is don't care
+*/
+#define MR1_VAL 0x23
+
+/* MR10: ZQ calibration codes */
+#define MR10_ZQ_ZQCS 0x56
+#define MR10_ZQ_ZQCL 0xAB
+#define MR10_ZQ_ZQINIT 0xFF
+#define MR10_ZQ_ZQRESET 0xC3
+
+/* TEMP_ALERT_CONFIG */
+#define TEMP_ALERT_POLL_INTERVAL_MS 360 /* for temp gradient - 5 C/s */
+#define TEMP_ALERT_CONFIG_DEVCT_1 0
+#define TEMP_ALERT_CONFIG_DEVWDT_32 2
+
+/* MR16 value: refresh full array(no partial array self refresh) */
+#define MR16_VAL 0
+
+#if defined(DEBUG)
+#define emif_assert(c) BUG_ON(!(c))
+#else
+#define emif_assert(c) ({ if (0) BUG_ON(!(c)); 0; })
+#endif
+
+/* Details of the devices connected to each chip-select of an EMIF instance */
+struct emif_device_details {
+ const struct lpddr2_device_info *cs0_device;
+ const struct lpddr2_device_info *cs1_device;
+};
+
+/*
+ * LPDDR2 interface clock frequency:
+ * Period (represented as numerator and denominator for better accuracy in
+ * calculations) should be <= the real value. Period is used for calculating
+ * all timings except refresh rate.
+ * freq_mhz_floor - freq in mhz truncated to the lower integer is used for
+ * calculating refresh rate
+ * freq_mhz_ceil - frequency in mhz rounded up is used for identifying the
+ * right speed bin and the corresponding timings table for the LPDDR2 device
+ */
+struct freq_info {
+ u16 period_num;
+ u16 period_den;
+ u16 freq_mhz_floor;
+ u16 freq_mhz_ceil;
+};
+
+/*
+ * Structure containing shadow of important registers in EMIF
+ * The calculation function fills in this structure to be later used for
+ * initialization and DVFS
+ */
+struct emif_regs {
+ u32 freq;
+ u8 RL_final;
+ u32 sdram_config_init;
+ u32 sdram_config_final;
+ u32 ref_ctrl;
+ u32 ref_ctrl_derated;
+ u32 sdram_tim1;
+ u32 sdram_tim1_derated;
+ u32 sdram_tim2;
+ u32 sdram_tim3;
+ u32 read_idle_ctrl_normal;
+ u32 read_idle_ctrl_volt_ramp;
+ u32 zq_config_normal;
+ u32 zq_config_volt_ramp;
+ u32 temp_alert_config;
+ u32 temp_alert_config_derated;
+ u32 emif_ddr_phy_ctlr_1_init;
+ u32 emif_ddr_phy_ctlr_1_final;
+};
+
+int omap_emif_setup_registers(u32 freq,
+ u32 volt_state);
+void omap_emif_frequency_pre_notify(void);
+void omap_emif_frequency_post_notify(void);
+int omap_emif_setup_device_details(
+ const struct emif_device_details *emif1_devices,
+ const struct emif_device_details *emif2_devices);
+
+void emif_clear_irq(int emif_id);
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/id.h b/arch/arm/mach-omap2/include/mach/id.h
index 02ed3aa..096c02b 100644
--- a/arch/arm/mach-omap2/include/mach/id.h
+++ b/arch/arm/mach-omap2/include/mach/id.h
@@ -18,5 +18,6 @@ struct omap_die_id {
};
void omap_get_die_id(struct omap_die_id *odi);
+void omap_get_production_id(struct omap_die_id *odi);
#endif
diff --git a/arch/arm/mach-omap2/include/mach/lpddr2-elpida.h b/arch/arm/mach-omap2/include/mach/lpddr2-elpida.h
new file mode 100644
index 0000000..b1accb8
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/lpddr2-elpida.h
@@ -0,0 +1,23 @@
+/*
+ * ELPIDA LPDDR2 timings.
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Aneesh V <aneesh@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.
+ */
+
+#ifndef _LPDDR2_ELPIDA_H
+#define _LPDDR2_ELPIDA_H
+
+extern const struct lpddr2_timings lpddr2_elpida_timings_200_mhz;
+extern const struct lpddr2_timings lpddr2_elpida_timings_333_mhz;
+extern const struct lpddr2_timings lpddr2_elpida_timings_400_mhz;
+extern const struct lpddr2_min_tck lpddr2_elpida_min_tck;
+extern struct lpddr2_device_info lpddr2_elpida_2G_S4_dev;
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/lpddr2-jedec.h b/arch/arm/mach-omap2/include/mach/lpddr2-jedec.h
new file mode 100644
index 0000000..4545c29
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/lpddr2-jedec.h
@@ -0,0 +1,149 @@
+/*
+ * LPDDR2 header based on JESD209-2
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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.
+ */
+
+#ifndef _LPDDR2_JDEC_H
+#define _LPDDR2_JDEC_H
+
+#include <linux/types.h>
+
+/*
+ * Maximum number of entries we keep in our array of timing tables
+ * We need not keep all the speed bins supported by the device
+ * We need to keep timing tables for only the speed bins that we
+ * are interested in
+ */
+#define MAX_NUM_SPEEDBINS 4
+
+/* LPDDR2 Densities */
+#define LPDDR2_DENSITY_64Mb 0
+#define LPDDR2_DENSITY_128Mb 1
+#define LPDDR2_DENSITY_256Mb 2
+#define LPDDR2_DENSITY_512Mb 3
+#define LPDDR2_DENSITY_1Gb 4
+#define LPDDR2_DENSITY_2Gb 5
+#define LPDDR2_DENSITY_4Gb 6
+#define LPDDR2_DENSITY_8Gb 7
+#define LPDDR2_DENSITY_16Gb 8
+#define LPDDR2_DENSITY_32Gb 9
+
+/* LPDDR2 type */
+#define LPDDR2_TYPE_S4 0
+#define LPDDR2_TYPE_S2 1
+#define LPDDR2_TYPE_NVM 2
+
+/* LPDDR2 IO width */
+#define LPDDR2_IO_WIDTH_32 0
+#define LPDDR2_IO_WIDTH_16 1
+#define LPDDR2_IO_WIDTH_8 2
+
+/* Mode register numbers */
+#define LPDDR2_MR0 0
+#define LPDDR2_MR1 1
+#define LPDDR2_MR2 2
+#define LPDDR2_MR3 3
+#define LPDDR2_MR4 4
+#define LPDDR2_MR5 5
+#define LPDDR2_MR6 6
+#define LPDDR2_MR7 7
+#define LPDDR2_MR8 8
+#define LPDDR2_MR9 9
+#define LPDDR2_MR10 10
+#define LPDDR2_MR11 11
+#define LPDDR2_MR16 16
+#define LPDDR2_MR17 17
+#define LPDDR2_MR18 18
+
+/* MR4 register fields */
+#define MR4_SDRAM_REF_RATE_SHIFT 0
+#define MR4_SDRAM_REF_RATE_MASK 7
+#define MR4_TUF_SHIFT 7
+#define MR4_TUF_MASK (1 << 7)
+
+/* MR4 SDRAM Refresh Rate field values */
+#define SDRAM_TEMP_NOMINAL 0x3
+#define SDRAM_TEMP_RESERVED_4 0x4
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6
+#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7
+
+struct lpddr2_addressing {
+ u8 num_banks;
+ u8 t_REFI_us_x10;
+ u8 row_sz[2]; /* One entry each for x32 and x16 */
+ u8 col_sz[2]; /* One entry each for x32 and x16 */
+};
+
+/* Structure for timings from the DDR datasheet */
+struct lpddr2_timings {
+ u32 max_freq;
+ u8 RL;
+ u8 tRPab;
+ u8 tRCD;
+ u8 tWR;
+ u8 tRASmin;
+ u8 tRRD;
+ u8 tWTRx2;
+ u8 tXSR;
+ u8 tXPx2;
+ u8 tRFCab;
+ u8 tRTPx2;
+ u8 tCKE;
+ u8 tCKESR;
+ u8 tZQCS;
+ u32 tZQCL;
+ u32 tZQINIT;
+ u8 tDQSCKMAXx2;
+ u8 tRASmax;
+ u8 tFAW;
+};
+
+/*
+ * Min tCK values for some of the parameters:
+ * If the calculated clock cycles for the respective parameter is
+ * less than the corresponding min tCK value, we need to set the min
+ * tCK value. This may happen at lower frequencies.
+ */
+struct lpddr2_min_tck {
+ u32 tRL;
+ u32 tRP_AB;
+ u32 tRCD;
+ u32 tWR;
+ u32 tRAS_MIN;
+ u32 tRRD;
+ u32 tWTR;
+ u32 tXP;
+ u32 tRTP;
+ u8 tCKE;
+ u32 tCKESR;
+ u32 tFAW;
+};
+
+struct lpddr2_device_info {
+ const struct lpddr2_timings *device_timings[MAX_NUM_SPEEDBINS];
+ const struct lpddr2_min_tck *min_tck;
+ u8 type;
+ u8 density;
+ u8 io_width;
+
+ /* Idle time in cycles to wait before putting the memory in self refresh */
+ s32 emif_ddr_selfrefresh_cycles;
+};
+
+/* The following are exported for devices which use JDEC specifications */
+extern const struct lpddr2_addressing lpddr2_jedec_addressing_table[];
+extern const struct lpddr2_timings lpddr2_jedec_timings_400_mhz;
+extern const struct lpddr2_timings lpddr2_jedec_timings_333_mhz;
+extern const struct lpddr2_timings lpddr2_jedec_timings_200_mhz;
+extern const struct lpddr2_min_tck lpddr2_jedec_min_tck;
+
+#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..f37cf4e 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -13,25 +13,84 @@
#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
+
+/*
+ * Secure HAL, PPA services available
+ */
+#define PPA_SERVICE_0 0x21
+#define PPA_SERVICE_PL310_POR 0x23
+#define PPA_SERVICE_DEFAULT_POR_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
+
+/*
+ * SAR restore phase USB HOST static port
+ * configuration
+ */
+#define OMAP4_USBHOST_CLKSEL_UTMI_P2_INT_P1_INT 0x0
+#define OMAP4_USBHOST_CLKSEL_UTMI_P2_INT_P1_EXT 0x1
+#define OMAP4_USBHOST_CLKSEL_UTMI_P2_EXT_P1_INT 0x2
+#define OMAP4_USBHOST_CLKSEL_UTMI_P2_EXT_P1_EXT 0x3
+
+#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 void *omap_get_dram_barrier_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 u32 gic_cpu_read(u32 reg);
extern void omap_smc1(u32 fn, u32 arg);
+extern void omap_bus_sync(void);
+extern void omap_do_wfi(void);
+
+extern bool gic_dist_disabled(void);
+extern void gic_timer_retrigger(void);
+
+/*
+ * 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 */
@@ -39,5 +98,65 @@ 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);
+
+#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 */
+
+extern int omap4_prcm_freq_update(void);
+
+#ifdef CONFIG_PM
+extern int omap4_sar_save(void);
+extern void omap4_sar_overwrite(void);
+extern void omap4_sar_usbhost_init(u32 fck_source);
+#else
+void omap4_sar_save(void)
+{
+}
+void omap4_sar_overwrite(void)
+{
+}
+void omap4_sar_usbhost_init(u32 fck_source)
+{
+}
#endif
-#endif
+
+#endif /* __ASSEMBLER__ */
+#endif /* OMAP_ARCH_OMAP4_COMMON_H */
diff --git a/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h b/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h
new file mode 100644
index 0000000..4378a77
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_OMAP_FIQ_DEBUGGER_H
+#define __MACH_OMAP_FIQ_DEBUGGER_H
+
+#ifdef CONFIG_OMAP_FIQ_DEBUGGER
+int __init omap_serial_debug_init(int id, bool is_fiq, bool is_high_prio_irq,
+ struct omap_device_pad *pads, int num_pads);
+u32 omap_debug_uart_resume_idle(void);
+
+#else
+static inline int __init omap_serial_debug_init(int id, bool is_fiq, bool is_high_prio_irq,
+ struct omap_device_pad *pads, int num_pads)
+{
+ return 0;
+}
+
+static inline u32 omap_debug_uart_resume_idle(void)
+{
+ return 0;
+}
+#endif
+
+#endif
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..0fdb6eb
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/tiler.h
@@ -0,0 +1,513 @@
+/*
+ * 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>
+
+/*
+ * ----------------------------- 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
+ * @param virt_array Array of physical address for the start of each virtual
+ page
+ *
+ * @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,
+ u32 *virt_array);
+
+/**
+ * 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 addr_array Array of addresses
+ * @param nents Number of addresses in array
+ *
+ * @return error status.
+ */
+s32 tiler_pin_block(tiler_blk_handle handle, u32 *addr_array, 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 memory requirements for a given container allocation
+ *
+ * @param fmt Tiler bpp mode
+ * @param width Width in pixels
+ * @param height Height in pixels
+ * @param alloc_pages Number of pages required to back tiler container
+ * @param virt_pages Number of pages required to back the virtual address space
+ *
+ * @return 0 for success. Non zero for error
+ */
+s32 tiler_memsize(enum tiler_fmt fmt, u32 width, u32 height, u32 *alloc_pages,
+ u32 *virt_pages);
+
+/**
+ * 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);
+
+struct tiler_pa_info *user_block_to_pa(u32 usr_addr, u32 num_pg);
+void tiler_pa_free(struct tiler_pa_info *pa);
+
+/*
+ * ---------------------------- 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..f42a4a3 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
@@ -84,18 +85,25 @@ static void __iommu_set_twl(struct iommu *obj, bool on)
iommu_write_reg(obj, l, MMU_CNTL);
}
-
static int omap2_iommu_enable(struct iommu *obj)
{
u32 l, pa;
unsigned long timeout;
+ int ret = 0;
+
+ if (!obj->secure_mode) {
+ if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
+ return -EINVAL;
- if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
- return -EINVAL;
+ pa = virt_to_phys(obj->iopgd);
+ if (!IS_ALIGNED(pa, SZ_16K))
+ return -EINVAL;
+ } else
+ pa = (u32)obj->secure_ttb;
- pa = virt_to_phys(obj->iopgd);
- 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);
@@ -124,11 +132,16 @@ static int omap2_iommu_enable(struct iommu *obj)
__iommu_set_twl(obj, true);
+ if (cpu_is_omap44xx())
+ iommu_write_reg(obj, 0x1, MMU_GP_REG);
+
return 0;
}
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 +149,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)
@@ -168,7 +183,6 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
if (stat & MMU_IRQ_MULTIHITFAULT)
errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
- iommu_write_reg(obj, stat, MMU_IRQSTATUS);
return errs;
}
@@ -225,7 +239,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/ldo.c b/arch/arm/mach-omap2/ldo.c
new file mode 100644
index 0000000..13ee2a3
--- /dev/null
+++ b/arch/arm/mach-omap2/ldo.c
@@ -0,0 +1,333 @@
+/*
+ * OMAP3/4 LDO users core
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Mike Turquette <mturquette@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/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <plat/cpu.h>
+#include "voltage.h"
+#include "ldo.h"
+
+/**
+ * _is_abb_enabled() - check if abb is enabled
+ * @voltdm: voltage domain to check for
+ * @abb: abb instance pointer
+ *
+ * Returns true if enabled, else returns false
+ */
+static inline bool _is_abb_enabled(struct voltagedomain *voltdm,
+ struct omap_ldo_abb_instance *abb)
+{
+ return (voltdm->read(abb->setup_reg) & abb->setup_bits->enable_mask) ?
+ true : false;
+}
+
+/**
+ * _abb_set_availability() - sets the availability of the ABB LDO
+ * @voltdm: voltage domain for which we would like to set
+ * @abb: abb instance pointer
+ * @available: should I enable/disable the LDO?
+ *
+ * Depending on the request, it enables/disables the LDO if it was not
+ * in that state already.
+ */
+static inline void _abb_set_availability(struct voltagedomain *voltdm,
+ struct omap_ldo_abb_instance *abb,
+ bool available)
+{
+ if (_is_abb_enabled(voltdm, abb) == available)
+ return;
+
+ voltdm->rmw(abb->setup_bits->enable_mask,
+ (available) ? abb->setup_bits->enable_mask : 0,
+ abb->setup_reg);
+}
+
+/**
+ * _abb_wait_tranx() - wait for abb tranxdone event
+ * @voltdm: voltage domain we are operating on
+ * @abb: pointer to the abb instance
+ *
+ * Returns -ETIMEDOUT if the event is not set on time.
+ */
+static int _abb_wait_tranx(struct voltagedomain *voltdm,
+ struct omap_ldo_abb_instance *abb)
+{
+ int timeout;
+ int ret;
+
+ timeout = 0;
+ while (timeout++ < abb->tranx_timeout) {
+ ret = abb->ops->check_txdone(abb->prm_irq_id);
+ if (ret)
+ break;
+
+ udelay(1);
+ }
+
+ if (timeout >= abb->tranx_timeout) {
+ pr_warning("%s:%s: ABB TRANXDONE waittimeout(timeout=%d)\n",
+ __func__, voltdm->name, timeout);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+/**
+ * _abb_clear_tranx() - clear abb tranxdone event
+ * @voltdm: voltage domain we are operating on
+ * @abb: pointer to the abb instance
+ *
+ * Returns -ETIMEDOUT if the event is not cleared on time.
+ */
+static int _abb_clear_tranx(struct voltagedomain *voltdm,
+ struct omap_ldo_abb_instance *abb)
+{
+ int timeout;
+ int ret;
+
+ /* clear interrupt status */
+ timeout = 0;
+ while (timeout++ < abb->tranx_timeout) {
+ abb->ops->clear_txdone(abb->prm_irq_id);
+
+ ret = abb->ops->check_txdone(abb->prm_irq_id);
+ if (!ret)
+ break;
+
+ udelay(1);
+ }
+
+ if (timeout >= abb->tranx_timeout) {
+ pr_warning("%s:%s: ABB TRANXDONE timeout(timeout=%d)\n",
+ __func__, voltdm->name, timeout);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+/**
+ * _abb_set_abb() - helper to actually set ABB (NOMINAL/FAST)
+ * @voltdm: voltage domain we are operating on
+ * @abb_type: ABB type we want to set
+ */
+static int _abb_set_abb(struct voltagedomain *voltdm, int abb_type)
+{
+ struct omap_ldo_abb_instance *abb = voltdm->abb;
+ int ret;
+
+ ret = _abb_clear_tranx(voltdm, abb);
+ if (ret)
+ return ret;
+
+ /* program next state of ABB ldo */
+ voltdm->rmw(abb->ctrl_bits->opp_sel_mask,
+ abb_type << __ffs(abb->ctrl_bits->opp_sel_mask),
+ abb->ctrl_reg);
+
+ /* initiate ABB ldo change */
+ voltdm->rmw(abb->ctrl_bits->opp_change_mask,
+ abb->ctrl_bits->opp_change_mask, abb->ctrl_reg);
+
+ /* Wait for conversion completion */
+ ret = _abb_wait_tranx(voltdm, abb);
+ WARN_ONCE(ret, "%s: voltdm %s ABB TRANXDONE was not set on time:%d\n",
+ __func__, voltdm->name, ret);
+ /* clear interrupt status */
+ ret |= _abb_clear_tranx(voltdm, abb);
+
+ return ret;
+}
+
+/**
+ * _abb_scale() - wrapper which does the necessary things for pre and post scale
+ * @voltdm: voltage domain to operate on
+ * @target_volt: voltage we are going to
+ * @is_prescale: are we doing a prescale operation?
+ *
+ * NOTE: We expect caller ensures that a specific voltdm is modified
+ * sequentially. All locking is expected to be implemented by users
+ * of LDO functions
+ */
+static int _abb_scale(struct voltagedomain *voltdm,
+ struct omap_volt_data *target_vdata, bool is_prescale)
+{
+ int ret = 0;
+ int curr_abb, target_abb;
+ struct omap_ldo_abb_instance *abb;
+
+ if (IS_ERR_OR_NULL(target_vdata)) {
+ pr_err("%s:%s: Invalid volt data tv=%p!\n", __func__,
+ voltdm->name, target_vdata);
+ return -EINVAL;
+ }
+
+ abb = voltdm->abb;
+ if (IS_ERR_OR_NULL(abb)) {
+ WARN(1, "%s:%s: no abb structure!\n", __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ curr_abb = abb->__cur_abb_type;
+ target_abb = target_vdata->abb_type;
+
+ pr_debug("%s: %s: Enter: t_v=%ld scale=%d c_abb=%d t_abb=%d ret=%d\n",
+ __func__, voltdm->name, omap_get_nominal_voltage(target_vdata),
+ is_prescale, curr_abb, target_abb, ret);
+
+ /* If we were'nt booting and there is no change, we get out */
+ if (target_abb == curr_abb && voltdm->curr_volt)
+ goto out;
+
+ /* Do we have an invalid ABB entry? scream for a fix! */
+ if (curr_abb == OMAP_ABB_NONE || target_abb == OMAP_ABB_NONE) {
+ WARN(1, "%s:%s: INVALID abb entries? curr=%d target=%d\n",
+ __func__, voltdm->name, curr_abb, target_abb);
+ return -EINVAL;
+ }
+
+ /*
+ * We set up ABB as follows:
+ * if we are scaling *to* a voltage which needs ABB, do it in post
+ * if we are scaling *from* a voltage which needs ABB, do it in pre
+ * So, if the conditions are in reverse, we just return happy
+ */
+ if (is_prescale && (target_abb > curr_abb))
+ goto out;
+
+ if (!is_prescale && (target_abb < curr_abb))
+ goto out;
+
+ /* Time to set ABB now */
+ ret = _abb_set_abb(voltdm, target_abb);
+ if (!ret) {
+ abb->__cur_abb_type = target_abb;
+ pr_debug("%s: %s: scaled - t_abb=%d!\n", __func__,
+ voltdm->name, target_abb);
+ } else {
+ pr_warning("%s: %s: failed scale: t_abb=%d (%d)!\n", __func__,
+ voltdm->name, target_abb, ret);
+ }
+
+out:
+ pr_debug("%s: %s:Exit: t_v=%ld scale=%d c_abb=%d t_abb=%d ret=%d\n",
+ __func__, voltdm->name, omap_get_nominal_voltage(target_vdata),
+ is_prescale, curr_abb, target_abb, ret);
+ return ret;
+
+}
+
+/**
+ * omap_ldo_abb_pre_scale() - Enable required ABB strategy before voltage scale
+ * @voltdm: voltage domain to operate on
+ * @target_volt: target voltage data we moved to.
+ */
+int omap_ldo_abb_pre_scale(struct voltagedomain *voltdm,
+ struct omap_volt_data *target_vdata)
+{
+ return _abb_scale(voltdm, target_vdata, true);
+}
+
+/**
+ * omap_ldo_abb_pre_scale() - Enable required ABB strategy after voltage scale
+ * @voltdm: voltage domain operated on
+ * @target_volt: target voltage we are going to
+ */
+int omap_ldo_abb_post_scale(struct voltagedomain *voltdm,
+ struct omap_volt_data *target_vdata)
+{
+ return _abb_scale(voltdm, target_vdata, false);
+}
+
+/**
+ * omap_ldo_abb_init() - initialize the ABB LDO for associated for this domain
+ * @voltdm: voltdm for which we need to initialize the ABB LDO
+ *
+ * Programs up the the configurations that dont change in the domain
+ *
+ * Return 0 if all goes fine, else returns appropriate error value
+ */
+void __init omap_ldo_abb_init(struct voltagedomain *voltdm)
+{
+ u32 sys_clk_rate;
+ u32 cycle_rate;
+ u32 settling_time;
+ u32 wait_count_val;
+ struct omap_ldo_abb_instance *abb;
+
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_err("%s: No voltdm?\n", __func__);
+ return;
+ }
+ if (!voltdm->read || !voltdm->write || !voltdm->rmw) {
+ pr_err("%s: No read/write/rmw API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ abb = voltdm->abb;
+ if (IS_ERR_OR_NULL(abb))
+ return;
+ if (IS_ERR_OR_NULL(abb->ctrl_bits) || IS_ERR_OR_NULL(abb->setup_bits)) {
+ pr_err("%s: Corrupted ABB configuration on vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ /*
+ * SR2_WTCNT_VALUE must be programmed with the expected settling time
+ * for ABB ldo transition. This value depends on the cycle rate for
+ * the ABB IP (varies per OMAP family), and the system clock frequency
+ * (varies per board). The formula is:
+ *
+ * SR2_WTCNT_VALUE = SettlingTime / (CycleRate / SystemClkRate))
+ * where SettlingTime is in micro-seconds and SystemClkRate is in MHz.
+ *
+ * To avoid dividing by zero multiply both CycleRate and SettlingTime
+ * by 10 such that the final result is the one we want.
+ */
+
+ /* Convert SYS_CLK rate to MHz & prevent divide by zero */
+ sys_clk_rate = DIV_ROUND_CLOSEST(voltdm->sys_clk.rate, 1000000);
+ cycle_rate = abb->cycle_rate * 10;
+ settling_time = abb->settling_time * 10;
+
+ /* Calculate cycle rate */
+ cycle_rate = DIV_ROUND_CLOSEST(cycle_rate, sys_clk_rate);
+
+ /* Calulate SR2_WTCNT_VALUE */
+ wait_count_val = DIV_ROUND_CLOSEST(settling_time, cycle_rate);
+
+ voltdm->rmw(abb->setup_bits->wait_count_mask,
+ wait_count_val << __ffs(abb->setup_bits->wait_count_mask),
+ abb->setup_reg);
+
+ /* Allow Forward Body-Bias */
+ voltdm->rmw(abb->setup_bits->active_fbb_mask,
+ abb->setup_bits->active_fbb_mask, abb->setup_reg);
+
+ /* Enable ABB */
+ _abb_set_availability(voltdm, abb, true);
+
+ /*
+ * Beware of the bootloader!
+ * Initialize current abb type based on what we read off the reg.
+ * we cant trust the initial state based off boot voltage's volt_data
+ * even. Not all bootloaders are nice :(
+ */
+ abb->__cur_abb_type = (voltdm->read(abb->ctrl_reg) &
+ abb->ctrl_bits->opp_sel_mask) >>
+ __ffs(abb->ctrl_bits->opp_sel_mask);
+
+ return;
+}
diff --git a/arch/arm/mach-omap2/ldo.h b/arch/arm/mach-omap2/ldo.h
new file mode 100644
index 0000000..44e66f4
--- /dev/null
+++ b/arch/arm/mach-omap2/ldo.h
@@ -0,0 +1,113 @@
+/*
+ * OMAP3/4 LDO structure and macro definitions
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Mike Turquette <mturquette@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 __ARCH_ARM_MACH_OMAP2_LDO_H
+#define __ARCH_ARM_MACH_OMAP2_LDO_H
+
+
+/**
+ * struct omap_ldo_abb_ops - ABB LDO status operation pointers
+ * @check_txdone: check if the transaction is done
+ * @clear_txdone: clear the transaction done event
+ */
+struct omap_ldo_abb_ops {
+ u32(*check_txdone) (u8 irq_id);
+ void (*clear_txdone) (u8 irq_id);
+};
+
+/*
+ * NOTE: OMAP3630 calls this the ctrl register, while
+ * OMAP4430, OMAP4460 is setup
+ */
+#define OMAP_LDO_ABB_SETUP_SR2_WTCNT_VALUE_MASK (0xFF << 8)
+#define OMAP_LDO_ABB_SETUP_ACTIVE_FBB_SEL_MASK BIT(2)
+#define OMAP_LDO_ABB_SETUP_SR2EN_MASK BIT(0)
+
+/**
+ * struct omap_ldo_abb_setup_bits - setup register bit defns
+ * @enable_mask: SR2EN field
+ * @active_fbb_mask: ACTIVE_FBB_SEL field
+ * @wait_count_mask: SR2_WTCNT_VALUE field
+ */
+struct omap_ldo_abb_setup_bits {
+ u32 enable_mask;
+ u32 active_fbb_mask;
+ /* RBB is not recommended to be used and hence not supported */
+ u32 wait_count_mask;
+};
+
+/*
+ * NOTE: OMAP3630 calls this the setup register, while
+ * OMAP4430, OMAP4460 is ctrl
+ */
+#define OMAP_LDO_ABB_CTRL_SR2_IN_TRANSITION_MASK BIT(6)
+#define OMAP_LDO_ABB_CTRL_SR2_STATUS_MASK (0x3 << 3)
+#define OMAP_LDO_ABB_CTRL_OPP_CHANGE_MASK BIT(2)
+#define OMAP_LDO_ABB_CTRL_OPP_SEL_MASK (0x3 << 0)
+
+/**
+ * struct omap_ldo_abb_ctrl_bits - ctrl register bit defns
+ * @in_tansition_mask: SR2_IN_TRANSITION field
+ * @status_mask: SR2_STATUS field
+ * @opp_change_mask: OPP_CHANGE field
+ * @opp_sel_mask: OPP_SEL field
+ */
+struct omap_ldo_abb_ctrl_bits {
+ u32 in_tansition_mask;
+ u32 status_mask;
+ u32 opp_change_mask;
+ u32 opp_sel_mask;
+};
+
+#define OMAP_ABB_TRANXDONE_TIMEOUT_US 50
+
+/**
+ * struct omap_ldo_abb_instance - Describe an LDO instance
+ * @prm_irq_id: PRM irq id for relevant for this block
+ * @ctrl_reg: control reg offset
+ * @setup_reg: setup reg offset
+ * @ctrl_bits: pointer to control register bitfield
+ * @setup_bits: pointer to setup register bitfield
+ * @settling_time: OMAP internal settling time(in uS)
+ * @cycle_rate: Cycle rate for the IP block
+ * @tranx_timeout: timeout count in uSec
+ * @ops: operations for ldo_abb
+ * @__cur_abb_type: private structure used by the driver, donot use.
+ */
+struct omap_ldo_abb_instance {
+ u8 prm_irq_id;
+
+ u32 ctrl_reg;
+ u32 setup_reg;
+ struct omap_ldo_abb_ctrl_bits *ctrl_bits;
+ struct omap_ldo_abb_setup_bits *setup_bits;
+
+ unsigned long settling_time;
+ unsigned long cycle_rate;
+ unsigned int tranx_timeout;
+
+ struct omap_ldo_abb_ops *ops;
+ int __cur_abb_type;
+};
+
+extern struct omap_ldo_abb_instance omap3630_ldo_abb_mpu_instance;
+
+extern struct omap_ldo_abb_instance omap4_ldo_abb_mpu_instance;
+extern struct omap_ldo_abb_instance omap4_ldo_abb_iva_instance;
+
+extern int omap_ldo_abb_pre_scale(struct voltagedomain *voltdm,
+ struct omap_volt_data *target_vdata);
+extern int omap_ldo_abb_post_scale(struct voltagedomain *voltdm,
+ struct omap_volt_data *target_vdata);
+extern void __init omap_ldo_abb_init(struct voltagedomain *voltdm);
+
+#endif /* __ARCH_ARM_MACH_OMAP2_LDO_H */
diff --git a/arch/arm/mach-omap2/ldo3xxx_data.c b/arch/arm/mach-omap2/ldo3xxx_data.c
new file mode 100644
index 0000000..870a912
--- /dev/null
+++ b/arch/arm/mach-omap2/ldo3xxx_data.c
@@ -0,0 +1,49 @@
+/*
+ * OMAP3xxx LDO data
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Mike Turquette <mturquette@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 "voltage.h"
+#include "ldo.h"
+#include "prm2xxx_3xxx.h"
+#include "prm-regbits-34xx.h"
+
+static struct omap_ldo_abb_ops omap3630_ldo_abb_ops = {
+ .check_txdone = omap36xx_prm_abb_check_txdone,
+ .clear_txdone = omap36xx_prm_abb_clear_txdone,
+};
+
+/* WARNING: OMAP3630 as per TRM rev J, has the register names inverted */
+
+static struct omap_ldo_abb_setup_bits omap3630_ldo_abb_setup_bits = {
+ .enable_mask = OMAP_LDO_ABB_SETUP_SR2EN_MASK,
+ .active_fbb_mask = OMAP_LDO_ABB_SETUP_ACTIVE_FBB_SEL_MASK,
+ .wait_count_mask = OMAP_LDO_ABB_SETUP_SR2_WTCNT_VALUE_MASK,
+};
+
+static struct omap_ldo_abb_ctrl_bits omap3630_ldo_abb_ctrl_bits = {
+ .in_tansition_mask = OMAP_LDO_ABB_CTRL_SR2_IN_TRANSITION_MASK,
+ .status_mask = OMAP_LDO_ABB_CTRL_SR2_STATUS_MASK,
+ .opp_change_mask = OMAP_LDO_ABB_CTRL_OPP_CHANGE_MASK,
+ .opp_sel_mask = OMAP_LDO_ABB_CTRL_OPP_SEL_MASK,
+};
+
+struct omap_ldo_abb_instance omap3630_ldo_abb_mpu_instance = {
+ .prm_irq_id = OMAP3_PRM_IRQ_VDD_MPU_ID,
+ .ctrl_reg = OMAP3_PRM_LDO_ABB_CTRL_OFFSET,
+ .setup_reg = OMAP3_PRM_LDO_ABB_SETUP_OFFSET,
+ .ctrl_bits = &omap3630_ldo_abb_ctrl_bits,
+ .setup_bits = &omap3630_ldo_abb_setup_bits,
+ .ops = &omap3630_ldo_abb_ops,
+
+ .settling_time = 30,
+ .cycle_rate = 8,
+ .tranx_timeout = OMAP_ABB_TRANXDONE_TIMEOUT_US,
+};
diff --git a/arch/arm/mach-omap2/ldo4xxx_data.c b/arch/arm/mach-omap2/ldo4xxx_data.c
new file mode 100644
index 0000000..161e957
--- /dev/null
+++ b/arch/arm/mach-omap2/ldo4xxx_data.c
@@ -0,0 +1,60 @@
+/*
+ * OMAP4xxx LDO data
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Mike Turquette <mturquette@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 "voltage.h"
+#include "ldo.h"
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+
+static struct omap_ldo_abb_ops omap4_ldo_abb_ops = {
+ .check_txdone = omap4_prm_abb_check_txdone,
+ .clear_txdone = omap4_prm_abb_clear_txdone,
+};
+
+static struct omap_ldo_abb_setup_bits omap4_ldo_abb_setup_bits = {
+ .enable_mask = OMAP_LDO_ABB_SETUP_SR2EN_MASK,
+ .active_fbb_mask = OMAP_LDO_ABB_SETUP_ACTIVE_FBB_SEL_MASK,
+ .wait_count_mask = OMAP_LDO_ABB_SETUP_SR2_WTCNT_VALUE_MASK,
+};
+
+static struct omap_ldo_abb_ctrl_bits omap4_ldo_abb_ctrl_bits = {
+ .in_tansition_mask = OMAP_LDO_ABB_CTRL_SR2_IN_TRANSITION_MASK,
+ .status_mask = OMAP_LDO_ABB_CTRL_SR2_STATUS_MASK,
+ .opp_change_mask = OMAP_LDO_ABB_CTRL_OPP_CHANGE_MASK,
+ .opp_sel_mask = OMAP_LDO_ABB_CTRL_OPP_SEL_MASK,
+};
+
+struct omap_ldo_abb_instance omap4_ldo_abb_mpu_instance = {
+ .prm_irq_id = OMAP4_PRM_IRQ_VDD_MPU_ID,
+ .ctrl_reg = OMAP4_PRM_LDO_ABB_MPU_CTRL_OFFSET,
+ .setup_reg = OMAP4_PRM_LDO_ABB_MPU_SETUP_OFFSET,
+ .ctrl_bits = &omap4_ldo_abb_ctrl_bits,
+ .setup_bits = &omap4_ldo_abb_setup_bits,
+ .ops = &omap4_ldo_abb_ops,
+
+ .settling_time = 50,
+ .cycle_rate = 16,
+ .tranx_timeout = OMAP_ABB_TRANXDONE_TIMEOUT_US,
+};
+
+struct omap_ldo_abb_instance omap4_ldo_abb_iva_instance = {
+ .prm_irq_id = OMAP4_PRM_IRQ_VDD_IVA_ID,
+ .ctrl_reg = OMAP4_PRM_LDO_ABB_IVA_CTRL_OFFSET,
+ .setup_reg = OMAP4_PRM_LDO_ABB_IVA_SETUP_OFFSET,
+ .ctrl_bits = &omap4_ldo_abb_ctrl_bits,
+ .setup_bits = &omap4_ldo_abb_setup_bits,
+ .ops = &omap4_ldo_abb_ops,
+
+ .settling_time = 50,
+ .cycle_rate = 16,
+ .tranx_timeout = OMAP_ABB_TRANXDONE_TIMEOUT_US,
+};
diff --git a/arch/arm/mach-omap2/lpddr2_elpida_data.c b/arch/arm/mach-omap2/lpddr2_elpida_data.c
new file mode 100644
index 0000000..aee63f1
--- /dev/null
+++ b/arch/arm/mach-omap2/lpddr2_elpida_data.c
@@ -0,0 +1,111 @@
+/*
+ * LPDDR2 data as per JESD209-2
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 <mach/emif.h>
+#include <mach/lpddr2-elpida.h>
+
+const struct lpddr2_timings lpddr2_elpida_timings_400_mhz = {
+ .max_freq = 400000000,
+ .RL = 6,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 15,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+const struct lpddr2_timings lpddr2_elpida_timings_333_mhz = {
+ .max_freq = 333000000,
+ .RL = 5,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 15,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+const struct lpddr2_timings lpddr2_elpida_timings_200_mhz = {
+ .max_freq = 200000000,
+ .RL = 3,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 20,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+const struct lpddr2_min_tck lpddr2_elpida_min_tck = {
+ .tRL = 3,
+ .tRP_AB = 3,
+ .tRCD = 3,
+ .tWR = 3,
+ .tRAS_MIN = 3,
+ .tRRD = 2,
+ .tWTR = 2,
+ .tXP = 2,
+ .tRTP = 2,
+ .tCKE = 3,
+ .tCKESR = 3,
+ .tFAW = 8
+};
+
+struct lpddr2_device_info lpddr2_elpida_2G_S4_dev = {
+ .device_timings = {
+ &lpddr2_elpida_timings_200_mhz,
+ &lpddr2_elpida_timings_333_mhz,
+ &lpddr2_elpida_timings_400_mhz
+ },
+ .min_tck = &lpddr2_elpida_min_tck,
+ .type = LPDDR2_TYPE_S4,
+ .density = LPDDR2_DENSITY_2Gb,
+ .io_width = LPDDR2_IO_WIDTH_32
+};
diff --git a/arch/arm/mach-omap2/lpddr2_jedec_data.c b/arch/arm/mach-omap2/lpddr2_jedec_data.c
new file mode 100644
index 0000000..e8b447c
--- /dev/null
+++ b/arch/arm/mach-omap2/lpddr2_jedec_data.c
@@ -0,0 +1,132 @@
+/*
+ * LPDDR2 data as per JESD209-2
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 <mach/lpddr2-jedec.h>
+#include <mach/emif.h>
+
+/*
+ * Organization and refresh requirements for LPDDR2 devices of different
+ * types and densities. Derived from JESD209-2 section 2.4
+ */
+const struct lpddr2_addressing lpddr2_jedec_addressing_table[] = {
+ /* Banks tREFIx10 rowx32,rowx16 colx32,colx16 density */
+ {BANKS4, T_REFI_15_6, {ROW_12, ROW_12}, {COL_7, COL_8} }, /*64M*/
+ {BANKS4, T_REFI_15_6, {ROW_12, ROW_12}, {COL_8, COL_9} }, /*128M*/
+ {BANKS4, T_REFI_7_8, {ROW_13, ROW_13}, {COL_8, COL_9} }, /*256M*/
+ {BANKS4, T_REFI_7_8, {ROW_13, ROW_13}, {COL_9, COL_10} }, /*512M*/
+ {BANKS8, T_REFI_7_8, {ROW_13, ROW_13}, {COL_9, COL_10} }, /*1GS4*/
+ {BANKS8, T_REFI_3_9, {ROW_14, ROW_14}, {COL_9, COL_10} }, /*2GS4*/
+ {BANKS8, T_REFI_3_9, {ROW_14, ROW_14}, {COL_10, COL_11} }, /*4G*/
+ {BANKS8, T_REFI_3_9, {ROW_15, ROW_15}, {COL_10, COL_11} }, /*8G*/
+ {BANKS4, T_REFI_7_8, {ROW_14, ROW_14}, {COL_9, COL_10} }, /*1GS2*/
+ {BANKS4, T_REFI_3_9, {ROW_15, ROW_15}, {COL_9, COL_10} }, /*2GS2*/
+};
+
+/*
+ * Base AC Timing values specified by JESD209-2 for 400MHz operation
+ * All devices will honour these timings at this frequency.
+ * Some devices may have better timings. Using these timings is safe when the
+ * timings are not available from the device data sheet.
+ */
+const struct lpddr2_timings lpddr2_jedec_timings_400_mhz = {
+ .max_freq = 400000000,
+ .RL = 6,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 15,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+/* Base AC Timing values specified by JESD209-2 for 333 MHz operation */
+const struct lpddr2_timings lpddr2_jedec_timings_333_mhz = {
+ .max_freq = 333000000,
+ .RL = 5,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 15,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+/* Base AC Timing values specified by JESD209-2 for 200 MHz operation */
+const struct lpddr2_timings lpddr2_jedec_timings_200_mhz = {
+ .max_freq = 200000000,
+ .RL = 3,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 20,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+/*
+ * Min tCK values specified by JESD209-2
+ * Min tCK specifies the minimum duration of some AC timing parameters in terms
+ * of the number of cycles. If the calculated number of cycles based on the
+ * absolute time value is less than the min tCK value, min tCK value should
+ * be used instead. This typically happens at low frequencies.
+ */
+const struct lpddr2_min_tck lpddr2_jedec_min_tck = {
+ .tRL = 3,
+ .tRP_AB = 3,
+ .tRCD = 3,
+ .tWR = 3,
+ .tRAS_MIN = 3,
+ .tRRD = 2,
+ .tWTR = 2,
+ .tXP = 2,
+ .tRTP = 2,
+ .tCKE = 3,
+ .tCKESR = 3,
+ .tFAW = 8
+};
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 86d564a..74750bf 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -14,33 +14,39 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <plat/mailbox.h>
#include <mach/irqs.h>
#define MAILBOX_REVISION 0x000
-#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
-#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
-#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
-#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
-#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
+#define MAILBOX_SYSCONFIG 0x10
+#define MAILBOX_MESSAGE(m) (0x040 + 0x4 * (m))
+#define MAILBOX_FIFOSTATUS(m) (0x080 + 0x4 * (m))
+#define MAILBOX_MSGSTATUS(m) (0x0c0 + 0x4 * (m))
+#define MAILBOX_IRQSTATUS(u) (0x100 + 0x8 * (u))
+#define MAILBOX_IRQENABLE(u) (0x104 + 0x8 * (u))
-#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 10 * (u))
+#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
+#define MAILBOX_SOFTRESET 1
-#define MBOX_REG_SIZE 0x120
-
-#define OMAP4_MBOX_REG_SIZE 0x130
-
-#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
-#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
+#define MBOX_NUM_USER 2
+#define OMAP4_MBOX_NUM_USER 3
+#define MBOX_NR_REGS 2
+#define OMAP4_MBOX_NR_REGS 3
static void __iomem *mbox_base;
+static u32 *mbox_ctx;
+static int nr_mbox_users;
+static bool context_saved;
+
struct omap_mbox2_fifo {
unsigned long msg;
unsigned long fifo_stat;
@@ -54,7 +60,6 @@ struct omap_mbox2_priv {
unsigned long irqstatus;
u32 newmsg_bit;
u32 notfull_bit;
- u32 ctx[OMAP4_MBOX_NR_REGS];
unsigned long irqdisable;
};
@@ -71,14 +76,66 @@ static inline void mbox_write_reg(u32 val, size_t ofs)
__raw_writel(val, mbox_base + ofs);
}
+static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
+{
+ int i;
+
+ if (context_saved)
+ return;
+
+ /* Save irqs per user */
+ for (i = 0; i < nr_mbox_users; i++) {
+ if (cpu_is_omap44xx())
+ mbox_ctx[i] = mbox_read_reg(OMAP4_MAILBOX_IRQENABLE(i));
+ else
+ mbox_ctx[i] = mbox_read_reg(MAILBOX_IRQENABLE(i));
+
+ dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+ i, mbox_ctx[i]);
+ }
+
+ context_saved = true;
+}
+
+static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
+{
+ int i;
+
+ if (!context_saved)
+ return;
+
+ /* Restore irqs per user */
+ for (i = 0; i < nr_mbox_users; i++) {
+ if (cpu_is_omap44xx())
+ mbox_write_reg(mbox_ctx[i], OMAP4_MAILBOX_IRQENABLE(i));
+ else
+ mbox_write_reg(mbox_ctx[i], MAILBOX_IRQENABLE(i));
+
+ dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+ i, mbox_ctx[i]);
+ }
+
+ context_saved = false;
+}
+
/* Mailbox H/W preparations */
static int omap2_mbox_startup(struct omap_mbox *mbox)
{
u32 l;
+ u32 max_iter = 100;
pm_runtime_enable(mbox->dev->parent);
pm_runtime_get_sync(mbox->dev->parent);
+ mbox_write_reg(MAILBOX_SOFTRESET, MAILBOX_SYSCONFIG);
+ while (mbox_read_reg(MAILBOX_SYSCONFIG) & MAILBOX_SOFTRESET) {
+ if (WARN_ON(!max_iter--))
+ break;
+ udelay(1);
+ }
+
+ omap2_mbox_restore_ctx(mbox);
+
l = mbox_read_reg(MAILBOX_REVISION);
pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
@@ -89,6 +146,7 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
static void omap2_mbox_shutdown(struct omap_mbox *mbox)
{
+ omap2_mbox_save_ctx(mbox);
pm_runtime_put_sync(mbox->dev->parent);
pm_runtime_disable(mbox->dev->parent);
}
@@ -169,40 +227,6 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox,
return (int)(enable & status & bit);
}
-static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
-{
- int i;
- struct omap_mbox2_priv *p = mbox->priv;
- int nr_regs;
- if (cpu_is_omap44xx())
- nr_regs = OMAP4_MBOX_NR_REGS;
- else
- nr_regs = MBOX_NR_REGS;
- for (i = 0; i < nr_regs; i++) {
- p->ctx[i] = mbox_read_reg(i * sizeof(u32));
-
- dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
- i, p->ctx[i]);
- }
-}
-
-static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
-{
- int i;
- struct omap_mbox2_priv *p = mbox->priv;
- int nr_regs;
- if (cpu_is_omap44xx())
- nr_regs = OMAP4_MBOX_NR_REGS;
- else
- nr_regs = MBOX_NR_REGS;
- for (i = 0; i < nr_regs; i++) {
- mbox_write_reg(p->ctx[i], i * sizeof(u32));
-
- dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
- i, p->ctx[i]);
- }
-}
-
static struct omap_mbox_ops omap2_mbox_ops = {
.type = OMAP_MBOX_TYPE2,
.startup = omap2_mbox_startup,
@@ -373,17 +397,31 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -ENODEV;
+
mbox_base = ioremap(mem->start, resource_size(mem));
if (!mbox_base)
return -ENOMEM;
- ret = omap_mbox_register(&pdev->dev, list);
- if (ret) {
- iounmap(mbox_base);
- return ret;
+ nr_mbox_users = cpu_is_omap44xx() ? OMAP4_MBOX_NUM_USER : MBOX_NUM_USER;
+ mbox_ctx = kzalloc(sizeof(u32) * nr_mbox_users, GFP_KERNEL);
+ if (!mbox_ctx) {
+ ret = -ENOMEM;
+ goto unmap_base;
}
+ ret = omap_mbox_register(&pdev->dev, list);
+ if (ret)
+ goto free_ctx;
+
return 0;
+
+free_ctx:
+ kfree(mbox_ctx);
+unmap_base:
+ iounmap(mbox_base);
+ return ret;
}
static int __devexit omap2_mbox_remove(struct platform_device *pdev)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 4a6ef6a..6afbc0d 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_fck");
+ strcpy(pdata->clks_prcm_src, "prcm_fck");
+
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");
+ sprintf(pdata->clks_prcm_src, "mcbsp%d_sync_mux_ck", id);
+
+ /* 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 c7fb22a..c7d0b21 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -118,10 +118,8 @@ static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
}
}
- if (found == 0) {
- pr_err("%s: Could not set gpio%i\n", __func__, gpio);
+ if (found == 0)
return -ENODEV;
- }
if (found > 1) {
pr_info("%s: Multiple gpio paths (%d) for gpio%i\n", __func__,
@@ -153,6 +151,8 @@ int __init omap_mux_init_gpio(int gpio, int val)
return ret;
}
+ pr_err("%s: Could not set gpio%i\n", __func__, gpio);
+
return -ENODEV;
}
@@ -210,8 +210,6 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
return -EINVAL;
}
- pr_err("%s: Could not find signal %s\n", __func__, muxname);
-
return -ENODEV;
}
@@ -234,6 +232,8 @@ omap_mux_get_by_name(const char *muxname,
return mux_mode;
}
+ pr_err("%s: Could not find signal %s\n", __func__, muxname);
+
return -ENODEV;
}
@@ -351,6 +351,36 @@ err1:
return NULL;
}
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup event is set for pad else false
+ * if wakeup is not occured or pads are not avialable.
+ */
+int omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ int i;
+ unsigned int val;
+ u8 ret = false;
+
+ for (i = 0; i < hmux->nr_pads; i++) {
+ struct omap_device_pad *pad = &hmux->pads[i];
+
+ if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+ val = omap_mux_read(pad->partition,
+ pad->mux->reg_offset);
+ if (val & OMAP_WAKEUP_EVENT) {
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
/* Assumes the calling function takes care of locking */
void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
{
@@ -906,7 +936,7 @@ static struct omap_mux *omap_mux_get_by_gpio(
}
/* Needed for dynamic muxing of GPIO pins for off-idle */
-u16 omap_mux_get_gpio(int gpio)
+struct omap_mux *omap_mux_get_gpio(int gpio)
{
struct omap_mux_partition *partition;
struct omap_mux *m = NULL;
@@ -914,13 +944,10 @@ u16 omap_mux_get_gpio(int gpio)
list_for_each_entry(partition, &mux_partitions, node) {
m = omap_mux_get_by_gpio(partition, gpio);
if (m)
- return omap_mux_read(partition, m->reg_offset);
+ return m;
}
- if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
- pr_err("%s: Could not get gpio%i\n", __func__, gpio);
-
- return OMAP_MUX_TERMINATOR;
+ return NULL;
}
/* Needed for dynamic muxing of GPIO pins for off-idle */
@@ -941,6 +968,55 @@ void omap_mux_set_gpio(u16 val, int gpio)
pr_err("%s: Could not set gpio%i\n", __func__, gpio);
}
+bool omap_mux_get_wakeupevent(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m) || !cpu_is_omap44xx())
+ return false;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ return val & OMAP_WAKEUP_EVENT;
+}
+
+/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
+bool omap_mux_get_wakeupenable(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m))
+ return false;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ return val & OMAP_PIN_OFF_WAKEUPENABLE;
+}
+
+/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
+int omap_mux_set_wakeupenable(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m))
+ return -EINVAL;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ val |= OMAP_PIN_OFF_WAKEUPENABLE;
+ omap_mux_write(m->partition, val, m->reg_offset);
+
+ return 0;
+}
+
+/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
+int omap_mux_clear_wakeupenable(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m))
+ return -EINVAL;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ val &= ~OMAP_PIN_OFF_WAKEUPENABLE;
+ omap_mux_write(m->partition, val, m->reg_offset);
+
+ return 0;
+}
+
static struct omap_mux * __init omap_mux_list_add(
struct omap_mux_partition *partition,
struct omap_mux *src)
@@ -954,6 +1030,7 @@ static struct omap_mux * __init omap_mux_list_add(
m = &entry->mux;
entry->mux = *src;
+ m->partition = partition;
#ifdef CONFIG_OMAP_MUX
if (omap_mux_copy_names(src, m)) {
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 2132308..e631b5e 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -131,6 +131,7 @@ struct omap_mux_partition {
struct omap_mux {
u16 reg_offset;
u16 gpio;
+ struct omap_mux_partition *partition;
#ifdef CONFIG_OMAP_MUX
char *muxnames[OMAP_MUX_NR_MODES];
#ifdef CONFIG_DEBUG_FS
@@ -225,8 +226,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
*/
void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+int omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
#else
+static inline int
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ return 0;
+}
+
static inline int omap_mux_init_gpio(int gpio, int val)
{
return 0;
@@ -251,11 +265,31 @@ static struct omap_board_mux *board_mux __initdata __maybe_unused;
#endif
/**
- * omap_mux_get_gpio() - get mux register value based on GPIO number
+ * omap_mux_get_gpio() - get mux struct based on GPIO number
* @gpio: GPIO number
*
*/
-u16 omap_mux_get_gpio(int gpio);
+struct omap_mux *omap_mux_get_gpio(int gpio);
+
+/** omap_mux_set_wakeupenable() - set the wakeupenable bit on a mux struct
+ * @m: mux struct
+ */
+int omap_mux_set_wakeupenable(struct omap_mux *m);
+
+/** omap_mux_clear_wakeupenable() - clear the wakeupenable bit on a mux struct
+ * @m: mux struct
+ */
+int omap_mux_clear_wakeupenable(struct omap_mux *m);
+
+/** omap_mux_get_wakeupenable() - get the wakeupenable bit from a mux struct
+ * @m: mux struct
+ */
+bool omap_mux_get_wakeupenable(struct omap_mux *m);
+
+/** omap_mux_get_wakeupevent() - get the wakeupevent bit from a mux struct
+ * @m: mux struct
+ */
+bool omap_mux_get_wakeupevent(struct omap_mux *m);
/**
* omap_mux_set_gpio() - set mux register value based on GPIO number
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..6965b4d 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(void)
+{
+ 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..40e425a 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -17,7 +17,9 @@
*/
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/delay.h>
#include <linux/smp.h>
+#include <linux/hrtimer.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
@@ -26,13 +28,27 @@
#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)
{
+ /* Enable NS access to SMP bit for this CPU on HS devices */
+ if (cpu_is_omap443x() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+ omap4_secure_dispatcher(PPA_SERVICE_DEFAULT_POR_NS_SMP,
+ FLAG_START_CRITICAL,
+ 0, 0, 0, 0, 0);
+
/*
* If any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
@@ -49,6 +65,9 @@ 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 +83,57 @@ 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) {
+ /*
+ * GIC distributor control register has changed between
+ * CortexA9 r1pX and r2pX. The Control Register secure
+ * banked version is now composed of 2 bits:
+ * bit 0 == Secure Enable
+ * bit 1 == Non-Secure Enable
+ * The Non-Secure banked register has not changed
+ * Because the ROM Code is based on the r1pX GIC, the CPU1
+ * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+ * The workaround must be:
+ * 1) Before doing the CPU1 wakeup, CPU0 must disable
+ * the GIC distributor
+ * 2) CPU1 must re-enable the GIC distributor on
+ * it's wakeup path.
+ */
+ if (!cpu_is_omap443x()) {
+ local_irq_disable();
+ gic_dist_disable();
+ }
+
+ clkdm_wakeup(cpu1_clkdm);
+
+ if (!cpu_is_omap443x()) {
+ while (gic_dist_disabled()) {
+ udelay(1);
+ cpu_relax();
+ }
+ gic_timer_retrigger();
+ local_irq_enable();
+ }
+
+ } 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..7567ee6
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -0,0 +1,311 @@
+/*
+ * 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)
+{
+ 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)
+{
+ 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, d->node);
+ spin_unlock(&wakeupgen_lock);
+}
+
+/*
+ * Architecture specific Unmask extensiom
+ */
+static void wakeupgen_unmask(struct irq_data *d)
+{
+ spin_lock(&wakeupgen_lock);
+ _wakeupgen_set(d->irq, d->node);
+ spin_unlock(&wakeupgen_lock);
+}
+
+/**
+ * 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);
+}
+
+#ifdef CONFIG_PM
+/*
+ * Masking wakeup irqs is handled by the IRQCHIP_MASK_ON_SUSPEND flag,
+ * so no action is necessary in set_wake, but implement an empty handler
+ * here to prevent enable_irq_wake() returning an error.
+ */
+static int wakeupgen_set_wake(struct irq_data *d, unsigned int on)
+{
+ return 0;
+}
+#else
+#define wakeupgen_set_wake NULL
+#endif
+
+/*
+ * 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;
+ gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
+
+ 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..7c5a6f9
--- /dev/null
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -0,0 +1,439 @@
+/*
+ * 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 <linux/platform_device.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"
+
+#ifdef CONFIG_SMP
+struct lpj_info {
+ unsigned long ref;
+ unsigned int freq;
+};
+
+static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
+static struct lpj_info global_lpj_ref;
+#endif
+
+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 DEFINE_MUTEX(omap_cpufreq_lock);
+
+static unsigned int max_thermal;
+static unsigned int max_freq;
+static unsigned int current_target_freq;
+static bool omap_cpufreq_ready;
+static bool omap_cpufreq_suspended;
+
+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_cpufreq_scale(unsigned int target_freq, unsigned int cur_freq)
+{
+ unsigned int i;
+ int ret;
+ struct cpufreq_freqs freqs;
+
+ freqs.new = target_freq;
+ freqs.old = omap_getspeed(0);
+
+ /*
+ * If the new frequency is more than the thermal max allowed
+ * frequency, go ahead and scale the mpu device to proper frequency.
+ */
+ if (freqs.new > max_thermal)
+ freqs.new = max_thermal;
+
+ if ((freqs.old == freqs.new) && (cur_freq = freqs.new))
+ return 0;
+
+ get_online_cpus();
+
+ /* notifiers */
+ for_each_online_cpu(freqs.cpu)
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#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);
+
+ freqs.new = omap_getspeed(0);
+
+#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_possible_cpu(i) {
+ struct lpj_info *lpj = &per_cpu(lpj_ref, i);
+ if (!lpj->freq) {
+ lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
+ lpj->freq = freqs.old;
+ }
+
+ per_cpu(cpu_data, i).loops_per_jiffy =
+ cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
+ }
+
+ /* And don't forget to adjust the global one */
+ if (!global_lpj_ref.freq) {
+ global_lpj_ref.ref = loops_per_jiffy;
+ global_lpj_ref.freq = freqs.old;
+ }
+ loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
+ freqs.new);
+#endif
+
+ /* notifiers */
+ for_each_online_cpu(freqs.cpu)
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ put_online_cpus();
+
+ return ret;
+}
+
+static unsigned int omap_thermal_lower_speed(void)
+{
+ unsigned int max = 0;
+ unsigned int curr;
+ int i;
+
+ curr = max_thermal;
+
+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+ if (freq_table[i].frequency > max &&
+ freq_table[i].frequency < curr)
+ max = freq_table[i].frequency;
+
+ if (!max)
+ return curr;
+
+ return max;
+}
+
+void omap_thermal_throttle(void)
+{
+ unsigned int cur;
+
+ if (!omap_cpufreq_ready) {
+ pr_warn_once("%s: Thermal throttle prior to CPUFREQ ready\n",
+ __func__);
+ return;
+ }
+
+ mutex_lock(&omap_cpufreq_lock);
+
+ max_thermal = omap_thermal_lower_speed();
+
+ pr_warn("%s: temperature too high, cpu throttle at max %u\n",
+ __func__, max_thermal);
+
+ if (!omap_cpufreq_suspended) {
+ cur = omap_getspeed(0);
+ if (cur > max_thermal)
+ omap_cpufreq_scale(max_thermal, cur);
+ }
+
+ mutex_unlock(&omap_cpufreq_lock);
+}
+
+void omap_thermal_unthrottle(void)
+{
+ unsigned int cur;
+
+ if (!omap_cpufreq_ready)
+ return;
+
+ mutex_lock(&omap_cpufreq_lock);
+
+ if (max_thermal == max_freq) {
+ pr_warn("%s: not throttling\n", __func__);
+ goto out;
+ }
+
+ max_thermal = max_freq;
+
+ pr_warn("%s: temperature reduced, ending cpu throttling\n", __func__);
+
+ if (!omap_cpufreq_suspended) {
+ cur = omap_getspeed(0);
+ omap_cpufreq_scale(current_target_freq, cur);
+ }
+
+out:
+ mutex_unlock(&omap_cpufreq_lock);
+}
+
+static int omap_verify_speed(struct cpufreq_policy *policy)
+{
+ if (!freq_table)
+ return -EINVAL;
+ return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static int omap_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int i;
+ int ret = 0;
+
+ 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;
+ }
+
+ mutex_lock(&omap_cpufreq_lock);
+
+ current_target_freq = freq_table[i].frequency;
+
+ if (!omap_cpufreq_suspended)
+ ret = omap_cpufreq_scale(current_target_freq, policy->cur);
+
+
+ mutex_unlock(&omap_cpufreq_lock);
+
+ 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;
+ int i;
+
+ 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);
+
+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+ max_freq = max(freq_table[i].frequency, max_freq);
+ max_thermal = max_freq;
+
+ /*
+ * 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 omap_cpufreq_suspend_noirq(struct device *dev)
+{
+ mutex_lock(&omap_cpufreq_lock);
+ omap_cpufreq_suspended = true;
+ mutex_unlock(&omap_cpufreq_lock);
+ return 0;
+}
+
+static int omap_cpufreq_resume_noirq(struct device *dev)
+{
+ unsigned int cur;
+
+ mutex_lock(&omap_cpufreq_lock);
+ cur = omap_getspeed(0);
+ if (cur != current_target_freq)
+ omap_cpufreq_scale(current_target_freq, cur);
+
+ omap_cpufreq_suspended = false;
+ mutex_unlock(&omap_cpufreq_lock);
+ return 0;
+}
+
+static struct dev_pm_ops omap_cpufreq_driver_pm_ops = {
+ .suspend_noirq = omap_cpufreq_suspend_noirq,
+ .resume_noirq = omap_cpufreq_resume_noirq,
+};
+
+static struct platform_driver omap_cpufreq_platform_driver = {
+ .driver.name = "omap_cpufreq",
+ .driver.pm = &omap_cpufreq_driver_pm_ops,
+};
+static struct platform_device omap_cpufreq_device = {
+ .name = "omap_cpufreq",
+};
+
+static int __init omap_cpufreq_init(void)
+{
+ int ret;
+
+ 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;
+ }
+
+ ret = cpufreq_register_driver(&omap_driver);
+ omap_cpufreq_ready = !ret;
+
+ if (!ret) {
+ int t;
+
+ t = platform_device_register(&omap_cpufreq_device);
+ if (t)
+ pr_warn("%s_init: platform_device_register failed\n",
+ __func__);
+ t = platform_driver_register(&omap_cpufreq_platform_driver);
+ if (t)
+ pr_warn("%s_init: platform_driver_register failed\n",
+ __func__);
+ }
+
+ return ret;
+}
+
+static void __exit omap_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&omap_driver);
+ platform_driver_unregister(&omap_cpufreq_platform_driver);
+ platform_device_unregister(&omap_cpufreq_device);
+}
+
+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..7bf033c 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -14,38 +14,132 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_twd.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 0x7
+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 struct clockdomain *l4_secure_clkdm;
+static void *dram_barrier_base;
+
+static void omap_bus_sync_noop(void)
+{ }
+
+struct omap_bus_post_fns omap_bus_post = {
+ .sync = omap_bus_sync_noop,
+};
+EXPORT_SYMBOL(omap_bus_post);
+
+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 *omap_get_dram_barrier_base(void)
+{
+ return dram_barrier_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);
+}
+
+
+bool gic_dist_disabled(void)
+{
+ return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1);
+}
+
+void gic_dist_enable(void)
+{
+ if (cpu_is_omap443x() || gic_dist_disabled())
+ __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);
+}
+
+void gic_timer_retrigger(void)
+{
+ u32 twd_int = __raw_readl(twd_base + TWD_TIMER_INTSTAT);
+ u32 gic_int = __raw_readl(gic_dist_base_addr + GIC_DIST_PENDING_SET);
+ u32 twd_ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+
+ if (twd_int && !(gic_int & BIT(OMAP44XX_IRQ_LOCALTIMER))) {
+ /*
+ * The local timer interrupt got lost while the distributor was
+ * disabled. Ack the pending interrupt, and retrigger it.
+ */
+ pr_warn("%s: lost localtimer interrupt\n", __func__);
+ __raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+ if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) {
+ __raw_writel(1, twd_base + TWD_TIMER_COUNTER);
+ twd_ctrl |= TWD_TIMER_CONTROL_ENABLE;
+ __raw_writel(twd_ctrl, twd_base + TWD_TIMER_CONTROL);
+ }
+ }
+}
+
#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 +155,9 @@ 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;
+ bool mpu_prefetch_disable_errata = false;
/*
* To avoid code running on other OMAPs in
@@ -69,32 +166,77 @@ static int __init omap_l2_cache_init(void)
if (!cpu_is_omap44xx())
return -ENODEV;
+#ifdef CONFIG_OMAP_ALLOW_OSWR
+ if (omap_rev() == OMAP4460_REV_ES1_0)
+ mpu_prefetch_disable_errata = true;
+#endif
+
/* 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;
}
- if (omap_rev() != OMAP4430_REV_ES1_0)
- omap_smc1(0x109, aux_ctrl);
+ /*
+ * 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_EARLY_BRESP_SHIFT));
+
+ if (!mpu_prefetch_disable_errata)
+ aux_ctrl |= (1 << L2X0_AUX_CTRL_DATA_PREFETCH_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.
+ * It may cause single cache line memory corruption, leave it disabled
+ * on all devices
+ */
+ por_ctrl &= ~(1 << L2X0_PREFETCH_DOUBLE_LINEFILL_SHIFT);
+ if (!mpu_prefetch_disable_errata) {
+ por_ctrl |= 1 << L2X0_PREFETCH_DATA_PREFETCH_SHIFT;
+ por_ctrl |= L2X0_POR_OFFSET_VALUE;
+ }
+
+ /* Set POR through PPA service only in EMU/HS devices */
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+ omap4_secure_dispatcher(PPA_SERVICE_PL310_POR, 0x7, 1,
+ por_ctrl, 0, 0, 0);
+ else if (omap_rev() >= OMAP4430_REV_ES2_1)
+ omap_smc1(0x113, por_ctrl);
+
+
+ /*
+ * 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 (omap_rev() == OMAP4460_REV_ES1_0) {
+ 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);
+ }
+
+skip_aux_por_api:
/* Enable PL310 L2 Cache controller */
omap_smc1(0x102, 0x1);
@@ -111,3 +253,74 @@ static int __init omap_l2_cache_init(void)
}
early_initcall(omap_l2_cache_init);
#endif
+
+static int __init omap_barriers_init(void)
+{
+ dma_addr_t dram_phys;
+
+ if (!cpu_is_omap44xx())
+ return -ENODEV;
+
+ dram_barrier_base = dma_alloc_stronglyordered(NULL, SZ_4K,
+ (dma_addr_t *)&dram_phys, GFP_KERNEL);
+ if (!dram_barrier_base) {
+ pr_err("%s: failed to allocate memory.\n", __func__);
+ return -ENOMEM;
+ }
+
+ omap_bus_post.sync = omap_bus_sync;
+
+ return 0;
+}
+core_initcall(omap_barriers_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;
+
+ /* Look-up Only once */
+ if (!l4_secure_clkdm)
+ l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
+
+ /*
+ * 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..81511e8
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -0,0 +1,824 @@
+/*
+ * 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
+ * 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 "prcm_mpu44xx.h"
+#include "prminst44xx.h"
+#include "prcm44xx.h"
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "cm.h"
+#include "prm.h"
+#include "cm44xx.h"
+#include "prcm-common.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;
+};
+
+static void __iomem *gic_dist_base;
+static void __iomem *gic_cpu_base;
+static void __iomem *sar_base;
+
+static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
+
+#define PPI_CONTEXT_SIZE 11
+static DEFINE_PER_CPU(u32[PPI_CONTEXT_SIZE], gic_ppi_context);
+static DEFINE_PER_CPU(u32, gic_ppi_enable_mask);
+
+/* 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);
+}
+
+u32 gic_cpu_read(u32 reg)
+{
+ return __raw_readl(gic_cpu_base + reg);
+}
+
+/*
+ * 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);
+}
+
+struct reg_tuple {
+ void __iomem *addr;
+ u32 val;
+};
+
+static struct reg_tuple tesla_reg[] = {
+ {.addr = OMAP4430_CM_TESLA_CLKSTCTRL},
+ {.addr = OMAP4430_CM_TESLA_TESLA_CLKCTRL},
+ {.addr = OMAP4430_PM_TESLA_PWRSTCTRL},
+};
+
+static struct reg_tuple ivahd_reg[] = {
+ {.addr = OMAP4430_CM_IVAHD_CLKSTCTRL},
+ {.addr = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL},
+ {.addr = OMAP4430_CM_IVAHD_SL2_CLKCTRL},
+ {.addr = OMAP4430_PM_IVAHD_PWRSTCTRL}
+};
+
+static struct reg_tuple l3instr_reg[] = {
+ {.addr = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL},
+ {.addr = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL},
+ {.addr = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL},
+};
+
+/*
+ * 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;
+
+ switch (cpu_state) {
+ case PWRDM_POWER_RET:
+ scu_pwr_st = SCU_PM_DORMANT;
+ break;
+ case PWRDM_POWER_OFF:
+ scu_pwr_st = SCU_PM_POWEROFF;
+ break;
+ case PWRDM_POWER_ON:
+ case PWRDM_POWER_INACTIVE:
+ default:
+ scu_pwr_st = SCU_PM_NORMAL;
+ break;
+ }
+
+ __raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
+}
+
+static void gic_save_ppi(void)
+{
+ void __iomem *gic_dist_base = omap4_get_gic_dist_base();
+ u32 *context = __get_cpu_var(gic_ppi_context);
+ int i = 0;
+
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0x4);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0x8);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0xc);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0x10);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0x14);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0x18);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_PRI + 0x1c);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_CONFIG);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_CONFIG + 0x4);
+ context[i++] = readl_relaxed(gic_dist_base + GIC_DIST_ENABLE_SET);
+
+ BUG_ON(i != PPI_CONTEXT_SIZE);
+}
+
+static void gic_restore_ppi(void)
+{
+ void __iomem *gic_dist_base = omap4_get_gic_dist_base();
+ u32 *context = __get_cpu_var(gic_ppi_context);
+ int i = 0;
+
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0x4);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0x8);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0xc);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0x10);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0x14);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0x18);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_PRI + 0x1c);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_CONFIG);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_CONFIG + 0x4);
+ writel_relaxed(context[i++], gic_dist_base + GIC_DIST_ENABLE_SET);
+
+ BUG_ON(i != PPI_CONTEXT_SIZE);
+}
+
+/*
+ * Mask all the PPIs. This should only be called after they have been saved
+ * through secure trap or through save_ppi(). This is primarily needed to
+ * mask the local timer irq that could be pending since timekeeping gets
+ * suspended after the local irqs are disabled. The pending interrupt would
+ * kick the CPU out of WFI immediately, and prevent it from going to the lower
+ * power states. The correct value will be restored when the CPU is brought
+ * back up by restore.
+ */
+static void gic_mask_ppi(void)
+{
+ void __iomem *gic_dist_base = omap4_get_gic_dist_base();
+
+ __get_cpu_var(gic_ppi_enable_mask) =
+ readl_relaxed(gic_dist_base + GIC_DIST_ENABLE_SET);
+ writel_relaxed(0xffffffff, gic_dist_base + GIC_DIST_ENABLE_CLEAR);
+}
+
+static void gic_unmask_ppi(void)
+{
+ void __iomem *gic_dist_base = omap4_get_gic_dist_base();
+ writel_relaxed(__get_cpu_var(gic_ppi_enable_mask),
+ gic_dist_base + GIC_DIST_ENABLE_SET);
+}
+
+/*
+ * 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_START_CRITICAL,
+ 0, 0, 0, 0, 0);
+ if (!ret)
+ pr_debug("GIC and Wakeupgen context save failed\n");
+}
+
+
+/*
+ * API to save Secure RAM, GIC, WakeupGen Registers using secure API
+ * for HS/EMU device
+ */
+static void save_secure_all(void)
+{
+ u32 ret;
+ ret = omap4_secure_dispatcher(HAL_SAVEALL_INDEX,
+ FLAG_START_CRITICAL,
+ 1, omap4_secure_ram_phys, 0, 0, 0);
+ if (ret)
+ pr_debug("Secure all 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_START_CRITICAL,
+ 1, omap4_secure_ram_phys, 0, 0, 0);
+ if (!ret)
+ pr_debug("Secure ram context save failed\n");
+}
+
+/* Helper functions for MPUSS OSWR */
+static inline u32 mpuss_read_prev_logic_pwrst(void)
+{
+ u32 reg;
+
+ reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
+ reg &= OMAP4430_LOSTCONTEXT_DFF_MASK;
+ return reg;
+}
+
+static inline void mpuss_clear_prev_logic_pwrst(void)
+{
+ u32 reg;
+
+ reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
+ omap4_prminst_write_inst_reg(reg, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
+}
+
+static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id)
+{
+ u32 reg;
+
+ if (cpu_id) {
+ reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST,
+ OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
+ omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST,
+ OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
+ } else {
+ reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST,
+ OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
+ omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST,
+ OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
+ }
+}
+
+static inline void save_ivahd_tesla_regs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tesla_reg); i++)
+ tesla_reg[i].val = __raw_readl(tesla_reg[i].addr);
+
+ for (i = 0; i < ARRAY_SIZE(ivahd_reg); i++)
+ ivahd_reg[i].val = __raw_readl(ivahd_reg[i].addr);
+}
+
+static inline void restore_ivahd_tesla_regs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tesla_reg); i++)
+ __raw_writel(tesla_reg[i].val, tesla_reg[i].addr);
+
+ for (i = 0; i < ARRAY_SIZE(ivahd_reg); i++)
+ __raw_writel(ivahd_reg[i].val, ivahd_reg[i].addr);
+}
+
+static inline void save_l3instr_regs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(l3instr_reg); i++)
+ l3instr_reg[i].val = __raw_readl(l3instr_reg[i].addr);
+}
+
+static inline void restore_l3instr_regs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(l3instr_reg); i++)
+ __raw_writel(l3instr_reg[i].val, l3instr_reg[i].addr);
+}
+
+/*
+ * 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);
+ mpuss_clear_prev_logic_pwrst();
+ if (omap4_device_next_state_off()) {
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
+ omap_wakeupgen_save();
+ gic_save_context();
+ } else {
+ save_secure_all();
+ save_ivahd_tesla_regs();
+ save_l3instr_regs();
+ }
+ save_state = 3;
+ goto cpu_prepare;
+ }
+
+ switch (pwrdm_read_next_pwrst(mpuss_pd)) {
+ case PWRDM_POWER_RET:
+ /*
+ * MPUSS OSWR - Complete logic lost + L2$ retained.
+ * MPUSS CSWR - Complete logic retained + L2$ retained.
+ */
+ if (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF) {
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
+ omap_wakeupgen_save();
+ gic_save_context();
+ } else {
+ save_gic_wakeupgen_secure();
+ save_ivahd_tesla_regs();
+ save_l3instr_regs();
+ }
+ save_state = 2;
+ }
+ break;
+ case PWRDM_POWER_OFF:
+ /* MPUSS OFF - logic lost + L2$ lost */
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
+ omap_wakeupgen_save();
+ gic_save_context();
+ } else {
+ save_gic_wakeupgen_secure();
+ save_ivahd_tesla_regs();
+ save_l3instr_regs();
+ save_secure_ram();
+ }
+ save_state = 3;
+ break;
+ case PWRDM_POWER_ON:
+ case PWRDM_POWER_INACTIVE:
+ /* No need to save MPUSS context */
+ default:
+ ;
+ }
+
+cpu_prepare:
+ if (cpu)
+ gic_save_ppi();
+
+ /*
+ * mask all PPIs to prevent them from kicking us out of wfi.
+ */
+ gic_mask_ppi();
+
+ clear_cpu_prev_pwrst(cpu);
+ cpu_clear_prev_logic_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.
+ */
+ stop_critical_timings();
+ omap4_cpu_suspend(cpu, save_state);
+ start_critical_timings();
+
+ /*
+ * 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 we didn't actually get into the low power state (e.g. immediately
+ * exited wfi due to a pending interrupt), the secure side
+ * would not have restored CPU0's GIC PPI enable mask.
+ * For other CPUs, gic_restore_ppi will do that for us.
+ */
+ if (cpu)
+ gic_restore_ppi();
+ else
+ gic_unmask_ppi();
+
+ /*
+ * If !master cpu return to hotplug-path.
+ *
+ * GIC distributor control register has changed between
+ * CortexA9 r1pX and r2pX. The Control Register secure
+ * banked version is now composed of 2 bits:
+ * bit 0 == Secure Enable
+ * bit 1 == Non-Secure Enable
+ * The Non-Secure banked register has not changed
+ * Because the ROM Code is based on the r1pX GIC, the CPU1
+ * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+ * The workaround must be:
+ * 1) Before doing the CPU1 wakeup, CPU0 must disable
+ * the GIC distributor
+ * 2) CPU1 must re-enable the GIC distributor on
+ * it's wakeup path.
+ */
+ if (wakeup_cpu) {
+ if (!cpu_is_omap443x())
+ gic_dist_enable();
+ goto ret;
+ }
+
+ /* Check if MPUSS lost it's logic */
+ if (mpuss_read_prev_logic_pwrst()) {
+ /* Clear SAR BACKUP status on GP devices */
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP)
+ __raw_writel(0x0, sar_base + SAR_BACKUP_STATUS_OFFSET);
+ /* Enable GIC distributor and inteface on CPU0*/
+ gic_cpu_enable();
+ gic_dist_enable();
+
+ /*
+ * Dummy dispatcher call after OSWR and OFF
+ * Restore the right return Kernel address (with MMU on) for
+ * subsequent calls to secure ROM. Otherwise the return address
+ * will be to a PA return address and the system will hang.
+ */
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+ omap4_secure_dispatcher(PPA_SERVICE_0,
+ FLAG_START_CRITICAL,
+ 0, 0, 0, 0, 0);
+ }
+
+ if (omap4_device_prev_state_off()) {
+ restore_ivahd_tesla_regs();
+ restore_l3instr_regs();
+ }
+
+ 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);
+
+ /*
+ * Save the L2X0 PREFETCH_CTRL value to SAR memory.
+ * Its used in every restore path MPUSS OFF path.
+ */
+
+ val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
+ __raw_writel(val, sar_base + L2X0_PREFETCHCTRL_OFFSET);
+
+ /* Save L2X0 LOCKDOWN_OFFSET0 during SAR */
+ val = readl_relaxed(l2x0_base + 0x900);
+ writel_relaxed(val, sar_base + L2X0_LOCKDOWN_OFFSET0);
+#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();
+ gic_cpu_base = omap4_get_gic_cpu_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->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);
+ cpu_clear_prev_logic_pwrst(0);
+
+ /* 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->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);
+ cpu_clear_prev_logic_pwrst(1);
+
+ /* 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);
+ mpuss_clear_prev_logic_pwrst();
+
+ /*
+ * 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..851db59
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -0,0 +1,124 @@
+/*
+ * 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
+
+#include <mach/hardware.h>
+#include <mach/omap4-common.h>
+#include <mach/emif-44xx.h>
+#include <mach/dmm-44xx.h>
+#include <mach/ctrl_module_pad_core_44xx.h>
+
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "prcm-common.h"
+
+/*
+ * The SAR RAM is maintained during Device OFF mode.
+ * It is split into 4 banks with different privilege accesses
+ *
+ * ---------------------------------------------------------------------
+ * Access mode Bank Address Range
+ * ---------------------------------------------------------------------
+ * HS/GP : Public 1 0x4A32_6000 - 0x4A32_6FFF (4kB)
+ * HS/GP : Public, Secured
+ * if padconfaccdisable=1 2 0x4A32_7000 - 0x4A32_73FF (1kB)
+ * HS/EMU : Secured
+ * GP : Public 3 0x4A32_8000 - 0x4A32_87FF (2kB)
+ * HS/GP :
+ * Secure Priviledge,
+ * write once. 4 0x4A32_9000 - 0x4A32_93FF (1kB)
+ * ---------------------------------------------------------------------
+ * The SAR RAM save regiter layout is fixed since restore is done by hardware.
+ */
+
+#define MODULE_ADDR_IDX 0
+#define MODULE_OFFSET_IDX 1
+#define MODULE_NB_REGS_IDX 2
+#define SAR_RAM_OFFSET_IDX 3
+
+/*
+ * Module Index used to lookup VA using index
+ */
+#define MAX_SAR_MODULES 14
+#define EMIF1_INDEX 0
+#define EMIF2_INDEX 1
+#define DMM_INDEX 2
+#define CM1_INDEX 3
+#define CM2_INDEX 4
+#define C2C_INDEX 5
+#define CTRL_MODULE_PAD_CORE_INDEX 6
+#define L3_CLK1_INDEX 7
+#define L3_CLK2_INDEX 8
+#define L3_CLK3_INDEX 9
+#define USBTLL_INDEX 10
+#define UHH_INDEX 11
+#define L4CORE_INDEX 12
+#define L4PER_INDEX 13
+
+/*
+ * 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_AUXCTRL_OFFSET 0xd28
+#define OMAP_TYPE_OFFSET 0xd2c
+#define L2X0_LOCKDOWN_OFFSET0 0xd30
+#define L2X0_PREFETCHCTRL_OFFSET 0xd34
+#define L2X0_SAVE_OFFSET0 0xd38
+#define L2X0_SAVE_OFFSET1 0xd3c
+
+/* 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/omap4-sar.c b/arch/arm/mach-omap2/omap4-sar.c
new file mode 100644
index 0000000..85b5fe9
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-sar.c
@@ -0,0 +1,1054 @@
+/*
+ * OMAP4 Save Restore source file
+ *
+ * Copyright (C) 2010 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/platform_device.h>
+#include <linux/clk.h>
+
+#include <mach/omap4-common.h>
+#include <mach/ctrl_module_wkup_44xx.h>
+
+#include "clockdomain.h"
+#include "omap4-sar-layout.h"
+#include "cm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "cminst44xx.h"
+
+/*
+ * These SECURE control registers are used to work-around
+ * DDR corruption on the second chip select on OMAP443x.
+ */
+#define OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG 0x0114
+#define OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG 0x011c
+
+static void __iomem *sar_ram_base;
+static void __iomem *omap4_sar_modules[MAX_SAR_MODULES];
+static struct powerdomain *l3init_pwrdm;
+ static struct clockdomain *l3init_clkdm;
+static struct clk *usb_host_ck, *usb_tll_ck;
+
+/*
+ * SAR_RAM1 register layout consist of EMIF1, EMIF2, CM1, CM2,
+ * CONTROL_CORE efuse, DMM and USB TLL registers.
+ * The layout is arranged is a two dimentional array like
+ * below,
+ * const u32 sar_ramX_layout[nb_regs_sets][4] = {
+ * {module_index, reg_offset, size, sar_ram_offset},
+ * }
+ */
+static const u32 omap443x_sar_ram1_layout[][4] = {
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG, 1, 0x00000000},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG_2, 1, 0x00000004},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL, 1, 0x00000008},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW, 1, 0x0000000C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1, 1, 0x00000010},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1_SHDW, 1, 0x00000014},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2, 1, 0x00000018},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2_SHDW, 1, 0x0000001C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3, 1, 0x00000020},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3_SHDW, 1, 0x00000024},
+ {EMIF1_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM, 1, 0x00000028},
+ {EMIF1_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM_SHDW, 1, 0x0000002C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL, 1, 0x00000030},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW, 1, 0x00000034},
+ {EMIF1_INDEX, OMAP44XX_EMIF_OCP_CONFIG, 1, 0x00000038},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PERF_CNT_CFG, 1, 0x0000003C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PERF_CNT_SEL, 1, 0x00000040},
+ {EMIF1_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL, 1, 0x00000044},
+ {EMIF1_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW, 1, 0x00000048},
+ {EMIF1_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_SYS, 1, 0x0000004C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_LL, 1, 0x00000050},
+ {EMIF1_INDEX, OMAP44XX_EMIF_ZQ_CONFIG, 1, 0x00000054},
+ {EMIF1_INDEX, OMAP44XX_EMIF_TEMP_ALERT_CONFIG, 1, 0x00000058},
+ {EMIF1_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1, 1, 0x0000005C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW, 1, 0x00000060},
+ {EMIF1_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_2, 1, 0x00000064},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG, 1, 0x00000068},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG_2, 1, 0x0000006C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL, 1, 0x00000070},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW, 1, 0x00000074},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1, 1, 0x00000078},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1_SHDW, 1, 0x0000007C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2, 1, 0x00000080},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2_SHDW, 1, 0x00000084},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3, 1, 0x00000088},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3_SHDW, 1, 0x0000008C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM, 1, 0x00000090},
+ {EMIF2_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM_SHDW, 1, 0x00000094},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL, 1, 0x00000098},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW, 1, 0x0000009C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_OCP_CONFIG, 1, 0x000000A0},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PERF_CNT_CFG, 1, 0x000000A4},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PERF_CNT_SEL, 1, 0x000000A8},
+ {EMIF2_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL, 1, 0x000000AC},
+ {EMIF2_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW, 1, 0x000000B0},
+ {EMIF2_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_SYS, 1, 0x000000B4},
+ {EMIF2_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_LL, 1, 0x000000B8},
+ {EMIF2_INDEX, OMAP44XX_EMIF_ZQ_CONFIG, 1, 0x000000BC},
+ {EMIF2_INDEX, OMAP44XX_EMIF_TEMP_ALERT_CONFIG, 1, 0x000000C0},
+ {EMIF2_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1, 1, 0x000000C4},
+ {EMIF2_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW, 1, 0x000000C8},
+ {EMIF2_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_2, 1, 0x000000CC},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET, 1, 0x000000D0},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET, 1, 0x000000D4},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000D8},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000DC},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000E0},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000E4},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000E8},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000EC},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000F0},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000F4},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000F8},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000FC},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET, 1, 0x00000100},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET, 1, 0x00000104},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET, 1, 0x00000108},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET, 1, 0x0000010C},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET, 1, 0x00000110},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET, 1, 0x00000114},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000118},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET, 1, 0x0000011C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000120},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000124},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000128},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET, 1, 0x0000012C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET, 1, 0x00000130},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET, 1, 0x00000134},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET, 1, 0x00000138},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET, 1, 0x0000013C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET, 1, 0x00000140},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000144},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000148},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET, 1, 0x0000014C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000150},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000154},
+ {C2C_INDEX, 0x0C, 1, 0x00000158},
+ {C2C_INDEX, 0x10, 1, 0x0000015C},
+ {C2C_INDEX, 0x28, 1, 0x00000160},
+ {C2C_INDEX, 0x40, 1, 0x00000164},
+ {C2C_INDEX, 0x44, 1, 0x00000168},
+ {C2C_INDEX, 0x70, 1, 0x0000016C},
+ {C2C_INDEX, 0x74, 1, 0x00000170},
+ {C2C_INDEX, 0x84, 1, 0x00000174},
+ {C2C_INDEX, 0x88, 1, 0x00000178},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL, 15, 0x0000017C},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE, 14, 0x000001B8},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0, 8, 0x000001F0},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD, 1, 0x00000210},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C, 1, 0x00000214},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1, 1, 0x00000218},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2, 1, 0x0000021C},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4, 1, 0x00000220},
+ {DMM_INDEX, OMAP44XX_DMM_LISA_MAP, 4, 0x000000224},
+ {DMM_INDEX, OMAP44XX_DMM_LISA_LOCK, 1, 0x00000234},
+ {DMM_INDEX, OMAP44XX_DMM_TILER_OR, 2, 0x00000238},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_VIEW, 2, 0x00000240},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_VIEW_MAP, 4, 0x00000248},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_VIEW_MAP_BASE, 1, 0x00000258},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_IRQENABLE_SET, 1, 0x0000025C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR, 1, 0x00000260},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA, 1, 0x00000264},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL, 1, 0x00000268},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA, 1, 0x0000026C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR + 0x10, 1, 0x00000270},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA + 0x10, 1, 0x00000274},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL + 0x10, 1, 0x00000278},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA + 0x10, 1, 0x0000027C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR + 0x20, 1, 0x00000280},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA + 0x20, 1, 0x00000284},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL + 0x20, 1, 0x00000288},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA + 0x20, 1, 0x0000028C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR + 0x30, 1, 0x00000290},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA + 0x30, 1, 0x00000294},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL + 0x30, 1, 0x00000298},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA + 0x30, 1, 0x0000029C},
+ {DMM_INDEX, OMAP44XX_DMM_PEG_PRIO, 2, 0x000002A0},
+ {DMM_INDEX, OMAP44XX_DMM_PEG_PRIO_PAT, 1, 0x000002A8},
+ {L3_CLK1_INDEX, 0x508, 1, 0x000002AC},
+ {L3_CLK1_INDEX, 0x510, 1, 0x000002B0},
+ {L3_CLK1_INDEX, 0x708, 1, 0x000002B4},
+ {L3_CLK1_INDEX, 0x70C, 1, 0x000002B8},
+ {L3_CLK1_INDEX, 0x808, 1, 0x000002BC},
+ {L3_CLK2_INDEX, 0x1008, 1, 0x000002C0},
+ {L3_CLK2_INDEX, 0x1010, 1, 0x000002C4},
+ {L3_CLK2_INDEX, 0x1208, 1, 0x000002C8},
+ {L3_CLK2_INDEX, 0x1308, 1, 0x000002CC},
+ {L3_CLK2_INDEX, 0x130C, 1, 0x000002D0},
+ {L3_CLK2_INDEX, 0x1408, 1, 0x000002D4},
+ {L3_CLK2_INDEX, 0x140C, 1, 0x000002D8},
+ {L3_CLK2_INDEX, 0x1508, 1, 0x000002DC},
+ {L3_CLK2_INDEX, 0x150C, 1, 0x000002E0},
+ {L3_CLK3_INDEX, 0x208, 1, 0x000002E4},
+ {L3_CLK3_INDEX, 0x210, 1, 0x000002E8},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET, 1, 0x000002EC},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET, 1, 0x000002F0},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET, 1, 0x000002F4},
+ {USBTLL_INDEX, 0x400, 7, 0x000002F8},
+ {UHH_INDEX, 0x10, 1, 0x00000314},
+ {UHH_INDEX, 0x40, 1, 0x00000318},
+ {UHH_INDEX, 0x100, 384, 0x0000031C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET, 1, 0x0000091C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET, 1, 0x00000920},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET, 1, 0x00000924},
+};
+
+/*
+ * SAR_RAM2 register layout consist of SYSCTRL_PADCONF_CORE regsiters
+ */
+static const u32 omap443x_sar_ram2_layout[][4] = {
+ {CTRL_MODULE_PAD_CORE_INDEX, 0x40, 102, 0x00000000},
+};
+
+/*
+ * SAR_RAM3 and SAR_RAM4 layout is not listed since moslty it's handle by
+ * secure software.
+ */
+static const u32 omap443x_sar_ram3_layout[][4] = {
+ {L4CORE_INDEX, 0x2140, 1, 0x00000000},
+ {L4CORE_INDEX, 0x2104, 1, 0x00000004},
+ {L4CORE_INDEX, 0x2100, 1, 0x00000008},
+ {L4CORE_INDEX, 0x2108, 1, 0x0000000C},
+ {L4CORE_INDEX, 0x210C, 1, 0x00000010},
+ {L4CORE_INDEX, 0x2110, 1, 0x00000014},
+ {L4CORE_INDEX, 0x2114, 1, 0x00000018},
+ {L4CORE_INDEX, 0x204088, 14, 0x0000001C},
+ {L4CORE_INDEX, 0x206088, 2, 0x00000054},
+ {L4CORE_INDEX, 0x20C088, 30, 0x0000005C},
+ {L4CORE_INDEX, 0x210088, 30, 0x000000D4},
+ {L4CORE_INDEX, 0x212088, 38, 0x0000014C},
+ {L4CORE_INDEX, 0x214088, 2, 0x000001E4},
+ {L4CORE_INDEX, 0x216088, 2, 0x000001EC},
+ {L4CORE_INDEX, 0x218088, 2, 0x000001F4},
+ {L4CORE_INDEX, 0x21C088, 2, 0x000001FC},
+ {L4CORE_INDEX, 0x21E088, 2, 0x00000204},
+ {L4CORE_INDEX, 0x220088, 2, 0x0000020C},
+ {L4CORE_INDEX, 0x226088, 6, 0x00000214},
+ {L4CORE_INDEX, 0x228088, 2, 0x0000022C},
+ {L4CORE_INDEX, 0x22A088, 14, 0x00000234},
+ {L4PER_INDEX, 0x218, 1, 0x0000026C},
+ {L4PER_INDEX, 0x220, 1, 0x00000270},
+ {L4PER_INDEX, 0x228, 1, 0x00000274},
+ {L4PER_INDEX, 0x230, 1, 0x00000278},
+ {L4PER_INDEX, 0x238, 1, 0x0000027C},
+ {L4PER_INDEX, 0x298, 2, 0x00000280},
+ {L4PER_INDEX, 0x2A0, 2, 0x00000288},
+ {L4PER_INDEX, 0x2A8, 2, 0x00000290},
+ {L4PER_INDEX, 0x2B0, 2, 0x00000298},
+ {L4PER_INDEX, 0x2B8, 2, 0x000002A0},
+ {L4PER_INDEX, 0x304, 1, 0x000002A8},
+ {L4PER_INDEX, 0x31C, 1, 0x000002AC},
+ {L4PER_INDEX, 0x32C, 1, 0x000002B0},
+ {L4PER_INDEX, 0x33C, 1, 0x000002B4},
+ {L4PER_INDEX, 0x34C, 1, 0x000002B8},
+ {L4PER_INDEX, 0x35C, 1, 0x000002BC},
+ {L4PER_INDEX, 0x36C, 1, 0x000002C0},
+ {L4PER_INDEX, 0x37C, 1, 0x000002C4},
+ {L4PER_INDEX, 0x38C, 1, 0x000002C8},
+ {L4PER_INDEX, 0x39C, 1, 0x000002CC},
+ {L4PER_INDEX, 0x3AC, 1, 0x000002D0},
+ {L4PER_INDEX, 0x3BC, 1, 0x000002D4},
+ {L4PER_INDEX, 0x3CC, 1, 0x000002D8},
+ {L4PER_INDEX, 0x3D4, 1, 0x000002DC},
+ {L4PER_INDEX, 0x3E4, 1, 0x000002E0},
+ {L4PER_INDEX, 0x3F4, 1, 0x000002E4},
+ {L4PER_INDEX, 0x404, 1, 0x000002E8},
+ {L4PER_INDEX, 0x414, 1, 0x000002EC},
+ {L4PER_INDEX, 0x42C, 1, 0x000002F0},
+ {L4PER_INDEX, 0x43C, 1, 0x000002F4},
+ {L4PER_INDEX, 0x44C, 1, 0x000002F8},
+ {L4PER_INDEX, 0x45C, 1, 0x000002FC},
+ {L4PER_INDEX, 0x46C, 1, 0x00000300},
+ {L4PER_INDEX, 0x47C, 1, 0x00000304},
+ {L4PER_INDEX, 0x48C, 1, 0x00000308},
+ {L4PER_INDEX, 0x49C, 1, 0x0000030C},
+ {L4PER_INDEX, 0x4AC, 1, 0x00000310},
+ {L4PER_INDEX, 0x4BC, 1, 0x00000314},
+ {L4PER_INDEX, 0x4CC, 1, 0x00000318},
+ {L4PER_INDEX, 0x4DC, 1, 0x0000031C},
+ {L4PER_INDEX, 0x4EC, 1, 0x00000320},
+ {L4PER_INDEX, 0x4FC, 1, 0x00000324},
+ {L4PER_INDEX, 0x50C, 1, 0x00000328},
+ {L4PER_INDEX, 0x51C, 1, 0x0000032C},
+ {L4PER_INDEX, 0x52C, 1, 0x00000330},
+ {L4PER_INDEX, 0x53C, 1, 0x00000334},
+ {L4PER_INDEX, 0x54C, 1, 0x00000338},
+ {L4PER_INDEX, 0x55C, 1, 0x0000033C},
+ {L4PER_INDEX, 0x56C, 1, 0x00000340},
+ {L4PER_INDEX, 0x57C, 1, 0x00000344},
+ {L4PER_INDEX, 0x5A4, 1, 0x00000348},
+ {L4CORE_INDEX, 0x230, 1, 0x0000034C},
+ {L4CORE_INDEX, 0x238, 1, 0x00000350},
+ {L4CORE_INDEX, 0x2B0, 2, 0x00000354},
+ {L4CORE_INDEX, 0x2B8, 2, 0x0000035C},
+ {L4CORE_INDEX, 0x304, 1, 0x00000364},
+ {L4CORE_INDEX, 0x31C, 1, 0x00000368},
+ {L4CORE_INDEX, 0x32C, 1, 0x0000036C},
+ {L4CORE_INDEX, 0x33C, 1, 0x00000370},
+ {L4CORE_INDEX, 0x354, 1, 0x00000374},
+ {L4CORE_INDEX, 0x35C, 1, 0x00000378},
+ {L4CORE_INDEX, 0x36C, 1, 0x0000037C},
+ {L4CORE_INDEX, 0x37C, 1, 0x00000380},
+ {L4CORE_INDEX, 0x38C, 1, 0x00000384},
+ {L4CORE_INDEX, 0x3AC, 1, 0x00000388},
+ {L4CORE_INDEX, 0x3BC, 1, 0x0000038C},
+ {L4CORE_INDEX, 0x3CC, 1, 0x00000390},
+ {L4CORE_INDEX, 0x3DC, 1, 0x00000394},
+ {L4CORE_INDEX, 0x3EC, 1, 0x00000398},
+ {L4CORE_INDEX, 0x3FC, 1, 0x0000039C},
+ {L4CORE_INDEX, 0x40C, 1, 0x000003A0},
+ {L4CORE_INDEX, 0x41C, 1, 0x000003A4},
+ {L4CORE_INDEX, 0x42C, 1, 0x000003A8},
+ {L4CORE_INDEX, 0x43C, 1, 0x000003AC},
+ {L4CORE_INDEX, 0x44C, 1, 0x000003B0},
+ {L4CORE_INDEX, 0x45C, 1, 0x000003B4},
+ {L4CORE_INDEX, 0x46C, 1, 0x000003B8},
+ {L4CORE_INDEX, 0x47C, 1, 0x000003BC},
+ {L4CORE_INDEX, 0x48C, 1, 0x000003C0},
+ {L4CORE_INDEX, 0x49C, 1, 0x000003C4},
+ {L4CORE_INDEX, 0x4AC, 1, 0x000003C8},
+ {L4CORE_INDEX, 0x4BC, 1, 0x000003CC},
+ {L4CORE_INDEX, 0x4CC, 1, 0x000003D0},
+ {L4CORE_INDEX, 0x4DC, 1, 0x000003D4},
+ {L4CORE_INDEX, 0x4EC, 1, 0x000003D8},
+ {L4CORE_INDEX, 0x4FC, 1, 0x000003DC},
+ {L4CORE_INDEX, 0x50C, 1, 0x000003E0},
+ {L4CORE_INDEX, 0x51C, 1, 0x000003E4},
+ {L4CORE_INDEX, 0x52C, 1, 0x000003E8},
+ {L4CORE_INDEX, 0x53C, 1, 0x000003EC},
+ {L4CORE_INDEX, 0x54C, 1, 0x000003F0},
+ {L4CORE_INDEX, 0x55C, 1, 0x000003F4},
+ {L4CORE_INDEX, 0x56C, 1, 0x000003F8},
+ {L4CORE_INDEX, 0x574, 1, 0x000003FC},
+ {L4CORE_INDEX, 0x584, 1, 0x00000400},
+ {L4CORE_INDEX, 0x594, 1, 0x00000404},
+ {L4CORE_INDEX, 0x5A4, 1, 0x00000408},
+ {L4CORE_INDEX, 0x5B4, 1, 0x0000040C},
+ {L4CORE_INDEX, 0x5C4, 1, 0x00000410},
+ {L4CORE_INDEX, 0x5D4, 1, 0x00000414},
+ {L4CORE_INDEX, 0x5DC, 1, 0x00000418},
+};
+
+
+static const u32 omap446x_sar_ram1_layout[][4] = {
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG_2, 1, 0x00000000},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG, 1, 0x00000004},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL, 1, 0x00000008},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW, 1, 0x0000000C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1, 1, 0x00000010},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1_SHDW, 1, 0x00000014},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2, 1, 0x00000018},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2_SHDW, 1, 0x0000001C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3, 1, 0x00000020},
+ {EMIF1_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3_SHDW, 1, 0x00000024},
+ {EMIF1_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM, 1, 0x00000028},
+ {EMIF1_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM_SHDW, 1, 0x0000002C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL, 1, 0x00000030},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW, 1, 0x00000034},
+ {EMIF1_INDEX, OMAP44XX_EMIF_OCP_CONFIG, 1, 0x00000038},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PERF_CNT_CFG, 1, 0x0000003C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_PERF_CNT_SEL, 1, 0x00000040},
+ {EMIF1_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL, 1, 0x00000044},
+ {EMIF1_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW, 1, 0x00000048},
+ {EMIF1_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_SYS, 1, 0x0000004C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_LL, 1, 0x00000050},
+ {EMIF1_INDEX, OMAP44XX_EMIF_ZQ_CONFIG, 1, 0x00000054},
+ {EMIF1_INDEX, OMAP44XX_EMIF_TEMP_ALERT_CONFIG, 1, 0x00000058},
+ {EMIF1_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1, 1, 0x0000005C},
+ {EMIF1_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW, 1, 0x00000060},
+ {EMIF1_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_2, 1, 0x00000064},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG_2, 1, 0x00000068},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_CONFIG, 1, 0x0000006C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL, 1, 0x00000070},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW, 1, 0x00000074},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1, 1, 0x00000078},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_1_SHDW, 1, 0x0000007C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2, 1, 0x00000080},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_2_SHDW, 1, 0x00000084},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3, 1, 0x00000088},
+ {EMIF2_INDEX, OMAP44XX_EMIF_SDRAM_TIM_3_SHDW, 1, 0x0000008C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM, 1, 0x00000090},
+ {EMIF2_INDEX, OMAP44XX_EMIF_LPDDR2_NVM_TIM_SHDW, 1, 0x00000094},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL, 1, 0x00000098},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW, 1, 0x0000009C},
+ {EMIF2_INDEX, OMAP44XX_EMIF_OCP_CONFIG, 1, 0x000000A0},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PERF_CNT_CFG, 1, 0x000000A4},
+ {EMIF2_INDEX, OMAP44XX_EMIF_PERF_CNT_SEL, 1, 0x000000A8},
+ {EMIF2_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL, 1, 0x000000AC},
+ {EMIF2_INDEX, OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW, 1, 0x000000B0},
+ {EMIF2_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_SYS, 1, 0x000000B4},
+ {EMIF2_INDEX, OMAP44XX_EMIF_IRQENABLE_SET_LL, 1, 0x000000B8},
+ {EMIF2_INDEX, OMAP44XX_EMIF_ZQ_CONFIG, 1, 0x000000BC},
+ {EMIF2_INDEX, OMAP44XX_EMIF_TEMP_ALERT_CONFIG, 1, 0x000000C0},
+ {EMIF2_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1, 1, 0x000000C4},
+ {EMIF2_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW, 1, 0x000000C8},
+ {EMIF2_INDEX, OMAP44XX_EMIF_DDR_PHY_CTRL_2, 1, 0x000000CC},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET, 1, 0x000000D0},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET, 1, 0x000000D4},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000D8},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000DC},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000E0},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000E4},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000E8},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000EC},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000F0},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000F4},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000F8},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET, 1, 0x000000FC},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET, 1, 0x00000100},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET, 1, 0x00000104},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET, 1, 0x00000108},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET, 1, 0x0000010C},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET, 1, 0x00000110},
+ {CM1_INDEX, OMAP4430_CM1_RESTORE_INST +
+ OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET, 1, 0x00000114},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000118},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET, 1, 0x0000011C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000120},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000124},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET, 1, 0x00000128},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET, 1, 0x0000012C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET, 1, 0x00000130},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET, 1, 0x00000134},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET, 1, 0x00000138},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET, 1, 0x0000013C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET, 1, 0x00000140},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000144},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000148},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET, 1, 0x0000014C},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000150},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET, 1, 0x00000154},
+ {C2C_INDEX, 0x0C, 1, 0x00000158},
+ {C2C_INDEX, 0x10, 1, 0x0000015C},
+ {C2C_INDEX, 0x28, 1, 0x00000160},
+ {C2C_INDEX, 0x40, 1, 0x00000164},
+ {C2C_INDEX, 0x44, 1, 0x00000168},
+ {C2C_INDEX, 0x70, 1, 0x0000016C},
+ {C2C_INDEX, 0x74, 1, 0x00000170},
+ {C2C_INDEX, 0x84, 1, 0x00000174},
+ {C2C_INDEX, 0x88, 1, 0x00000178},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL, 15, 0x0000017C},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE, 14, 0x000001B8},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0, 8, 0x000001F0},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD, 1, 0x00000210},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C, 1, 0x00000214},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1, 1, 0x00000218},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2, 1, 0x0000021C},
+ {CTRL_MODULE_PAD_CORE_INDEX,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4, 1, 0x00000220},
+ {L4CORE_INDEX, 0x2350, 1, 0x00000224},
+ {DMM_INDEX, OMAP44XX_DMM_LISA_MAP, 4, 0x000000228},
+ {DMM_INDEX, OMAP44XX_DMM_LISA_LOCK, 1, 0x00000238},
+ {DMM_INDEX, OMAP44XX_DMM_TILER_OR, 2, 0x0000023C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_VIEW, 2, 0x00000244},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_VIEW_MAP, 4, 0x0000024C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_VIEW_MAP_BASE, 1, 0x0000025C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_IRQENABLE_SET, 1, 0x00000260},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR, 1, 0x00000264},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA, 1, 0x00000268},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL, 1, 0x0000026C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA, 1, 0x00000270},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR + 0x10, 1, 0x00000274},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA + 0x10, 1, 0x00000278},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL + 0x10, 1, 0x0000027C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA + 0x10, 1, 0x00000280},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR + 0x20, 1, 0x00000284},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA + 0x20, 1, 0x00000288},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL + 0x20, 1, 0x0000028C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA + 0x20, 1, 0x00000290},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DESCR + 0x30, 1, 0x00000294},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_AREA + 0x30, 1, 0x00000298},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_CTRL + 0x30, 1, 0x0000029C},
+ {DMM_INDEX, OMAP44XX_DMM_PAT_DATA + 0x30, 1, 0x000002A0},
+ {DMM_INDEX, OMAP44XX_DMM_PEG_PRIO, 2, 0x000002A4},
+ {DMM_INDEX, OMAP44XX_DMM_PEG_PRIO_PAT, 1, 0x000002AC},
+ {L3_CLK1_INDEX, 0x508, 1, 0x000002B0},
+ {L3_CLK1_INDEX, 0x510, 1, 0x000002B4},
+ {L3_CLK1_INDEX, 0x708, 1, 0x000002B8},
+ {L3_CLK1_INDEX, 0x70C, 1, 0x000002BC},
+ {L3_CLK1_INDEX, 0x808, 1, 0x000002C0},
+ {L3_CLK2_INDEX, 0x1008, 1, 0x000002C4},
+ {L3_CLK2_INDEX, 0x1010, 1, 0x000002C8},
+ {L3_CLK2_INDEX, 0x1208, 1, 0x000002CC},
+ {L3_CLK2_INDEX, 0x1308, 1, 0x000002D0},
+ {L3_CLK2_INDEX, 0x130C, 1, 0x000002D4},
+ {L3_CLK2_INDEX, 0x1408, 1, 0x000002D8},
+ {L3_CLK2_INDEX, 0x140C, 1, 0x000002DC},
+ {L3_CLK2_INDEX, 0x1508, 1, 0x000002E0},
+ {L3_CLK2_INDEX, 0x150C, 1, 0x000002E4},
+ {L3_CLK3_INDEX, 0x208, 1, 0x000002E8},
+ {L3_CLK3_INDEX, 0x210, 1, 0x000002EC},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET, 1, 0x000002F0},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET, 1, 0x000002F4},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET, 1, 0x000002F8},
+ {USBTLL_INDEX, 0x400, 7, 0x000002FC},
+ {UHH_INDEX, 0x10, 1, 0x00000318},
+ {UHH_INDEX, 0x40, 1, 0x0000031C},
+ {UHH_INDEX, 0x100, 384, 0x00000320},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET, 1, 0x00000920},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET, 1, 0x00000924},
+ {CM2_INDEX, OMAP4430_CM2_RESTORE_INST +
+ OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET, 1, 0x00000928},
+};
+
+/*
+ * SAR_RAM2 register layout consist of SYSCTRL_PADCONF_CORE regsiters
+ */
+static const u32 omap446x_sar_ram2_layout[][4] = {
+ {CTRL_MODULE_PAD_CORE_INDEX, 0x40, 102, 0x00000000},
+ {CTRL_MODULE_PAD_CORE_INDEX, 0x1f4, 1, 0x00000198},
+};
+
+/*
+ * SAR_RAM3 and SAR_RAM4 layout is not listed since moslty it's handle by
+ * secure software.
+ */
+static const u32 omap446x_sar_ram3_layout[][4] = {
+ {L4CORE_INDEX, 0x2140, 1, 0x00000000},
+ {L4CORE_INDEX, 0x2104, 1, 0x00000004},
+ {L4CORE_INDEX, 0x2100, 1, 0x00000008},
+ {L4CORE_INDEX, 0x2108, 1, 0x0000000C},
+ {L4CORE_INDEX, 0x210C, 1, 0x00000010},
+ {L4CORE_INDEX, 0x2110, 1, 0x00000014},
+ {L4CORE_INDEX, 0x2114, 1, 0x00000018},
+ {L4CORE_INDEX, 0x204088, 14, 0x0000001C},
+ {L4CORE_INDEX, 0x206088, 2, 0x00000054},
+ {L4CORE_INDEX, 0x20C088, 30, 0x0000005C},
+ {L4CORE_INDEX, 0x210088, 30, 0x000000D4},
+ {L4CORE_INDEX, 0x212088, 38, 0x0000014C},
+ {L4CORE_INDEX, 0x214088, 2, 0x000001E4},
+ {L4CORE_INDEX, 0x216088, 2, 0x000001EC},
+ {L4CORE_INDEX, 0x218088, 2, 0x000001F4},
+ {L4CORE_INDEX, 0x21C088, 2, 0x000001FC},
+ {L4CORE_INDEX, 0x21E088, 2, 0x00000204},
+ {L4CORE_INDEX, 0x220088, 2, 0x0000020C},
+ {L4CORE_INDEX, 0x226088, 6, 0x00000214},
+ {L4CORE_INDEX, 0x228088, 2, 0x0000022C},
+ {L4CORE_INDEX, 0x22A088, 14, 0x00000234},
+ {L4CORE_INDEX, 0x20A088, 30, 0x0000026C},
+ {L4PER_INDEX, 0x218, 1, 0x000002E4},
+ {L4PER_INDEX, 0x220, 1, 0x000002E8},
+ {L4PER_INDEX, 0x228, 1, 0x000002EC},
+ {L4PER_INDEX, 0x230, 1, 0x000002F0},
+ {L4PER_INDEX, 0x238, 1, 0x000002F4},
+ {L4PER_INDEX, 0x298, 2, 0x000002F8},
+ {L4PER_INDEX, 0x2A0, 2, 0x00000300},
+ {L4PER_INDEX, 0x2A8, 2, 0x00000308},
+ {L4PER_INDEX, 0x2B0, 2, 0x00000310},
+ {L4PER_INDEX, 0x2B8, 2, 0x00000318},
+ {L4PER_INDEX, 0x304, 1, 0x00000320},
+ {L4PER_INDEX, 0x31C, 1, 0x00000324},
+ {L4PER_INDEX, 0x32C, 1, 0x00000328},
+ {L4PER_INDEX, 0x33C, 1, 0x0000032C},
+ {L4PER_INDEX, 0x34C, 1, 0x00000330},
+ {L4PER_INDEX, 0x35C, 1, 0x00000334},
+ {L4PER_INDEX, 0x36C, 1, 0x00000338},
+ {L4PER_INDEX, 0x37C, 1, 0x0000033C},
+ {L4PER_INDEX, 0x38C, 1, 0x00000340},
+ {L4PER_INDEX, 0x39C, 1, 0x00000344},
+ {L4PER_INDEX, 0x3AC, 1, 0x00000348},
+ {L4PER_INDEX, 0x3BC, 1, 0x0000034C},
+ {L4PER_INDEX, 0x3CC, 1, 0x00000350},
+ {L4PER_INDEX, 0x3D4, 1, 0x00000354},
+ {L4PER_INDEX, 0x3E4, 1, 0x00000358},
+ {L4PER_INDEX, 0x3F4, 1, 0x0000035C},
+ {L4PER_INDEX, 0x404, 1, 0x00000360},
+ {L4PER_INDEX, 0x414, 1, 0x00000364},
+ {L4PER_INDEX, 0x42C, 1, 0x00000368},
+ {L4PER_INDEX, 0x43C, 1, 0x0000036C},
+ {L4PER_INDEX, 0x44C, 1, 0x00000370},
+ {L4PER_INDEX, 0x45C, 1, 0x00000374},
+ {L4PER_INDEX, 0x46C, 1, 0x00000378},
+ {L4PER_INDEX, 0x47C, 1, 0x0000037C},
+ {L4PER_INDEX, 0x48C, 1, 0x00000380},
+ {L4PER_INDEX, 0x49C, 1, 0x00000384},
+ {L4PER_INDEX, 0x4AC, 1, 0x00000388},
+ {L4PER_INDEX, 0x4BC, 1, 0x0000038C},
+ {L4PER_INDEX, 0x4CC, 1, 0x00000390},
+ {L4PER_INDEX, 0x4DC, 1, 0x00000394},
+ {L4PER_INDEX, 0x4EC, 1, 0x00000398},
+ {L4PER_INDEX, 0x4FC, 1, 0x0000039C},
+ {L4PER_INDEX, 0x50C, 1, 0x000003A0},
+ {L4PER_INDEX, 0x51C, 1, 0x000003A4},
+ {L4PER_INDEX, 0x52C, 1, 0x000003A8},
+ {L4PER_INDEX, 0x53C, 1, 0x000003AC},
+ {L4PER_INDEX, 0x54C, 1, 0x000003B0},
+ {L4PER_INDEX, 0x55C, 1, 0x000003B4},
+ {L4PER_INDEX, 0x56C, 1, 0x000003B8},
+ {L4PER_INDEX, 0x57C, 1, 0x000003BC},
+ {L4PER_INDEX, 0x5A4, 1, 0x000003C0},
+ {L4CORE_INDEX, 0x230, 1, 0x000003C4},
+ {L4CORE_INDEX, 0x238, 1, 0x000003C8},
+ {L4CORE_INDEX, 0x2B0, 2, 0x000003CC},
+ {L4CORE_INDEX, 0x2B8, 2, 0x000003D4},
+ {L4CORE_INDEX, 0x304, 1, 0x000003DC},
+ {L4CORE_INDEX, 0x31C, 1, 0x000003E0},
+ {L4CORE_INDEX, 0x32C, 1, 0x000003E4},
+ {L4CORE_INDEX, 0x33C, 1, 0x000003E8},
+ {L4CORE_INDEX, 0x354, 1, 0x000003EC},
+ {L4CORE_INDEX, 0x35C, 1, 0x000003F0},
+ {L4CORE_INDEX, 0x36C, 1, 0x000003F4},
+ {L4CORE_INDEX, 0x37C, 1, 0x000003F8},
+ {L4CORE_INDEX, 0x38C, 1, 0x000003FC},
+ {L4CORE_INDEX, 0x3AC, 1, 0x00000400},
+ {L4CORE_INDEX, 0x3BC, 1, 0x00000404},
+ {L4CORE_INDEX, 0x3CC, 1, 0x00000408},
+ {L4CORE_INDEX, 0x3DC, 1, 0x0000040C},
+ {L4CORE_INDEX, 0x3EC, 1, 0x00000410},
+ {L4CORE_INDEX, 0x3FC, 1, 0x00000414},
+ {L4CORE_INDEX, 0x40C, 1, 0x00000418},
+ {L4CORE_INDEX, 0x41C, 1, 0x0000041C},
+ {L4CORE_INDEX, 0x42C, 1, 0x00000420},
+ {L4CORE_INDEX, 0x43C, 1, 0x00000424},
+ {L4CORE_INDEX, 0x44C, 1, 0x00000428},
+ {L4CORE_INDEX, 0x45C, 1, 0x0000042C},
+ {L4CORE_INDEX, 0x46C, 1, 0x00000430},
+ {L4CORE_INDEX, 0x47C, 1, 0x00000434},
+ {L4CORE_INDEX, 0x48C, 1, 0x00000438},
+ {L4CORE_INDEX, 0x49C, 1, 0x0000043C},
+ {L4CORE_INDEX, 0x4AC, 1, 0x00000440},
+ {L4CORE_INDEX, 0x4BC, 1, 0x00000444},
+ {L4CORE_INDEX, 0x4CC, 1, 0x00000448},
+ {L4CORE_INDEX, 0x4DC, 1, 0x0000044C},
+ {L4CORE_INDEX, 0x4EC, 1, 0x00000450},
+ {L4CORE_INDEX, 0x4FC, 1, 0x00000454},
+ {L4CORE_INDEX, 0x50C, 1, 0x00000458},
+ {L4CORE_INDEX, 0x51C, 1, 0x0000045C},
+ {L4CORE_INDEX, 0x52C, 1, 0x00000460},
+ {L4CORE_INDEX, 0x53C, 1, 0x00000464},
+ {L4CORE_INDEX, 0x54C, 1, 0x00000468},
+ {L4CORE_INDEX, 0x55C, 1, 0x0000046C},
+ {L4CORE_INDEX, 0x56C, 1, 0x00000470},
+ {L4CORE_INDEX, 0x574, 1, 0x00000474},
+ {L4CORE_INDEX, 0x584, 1, 0x00000478},
+ {L4CORE_INDEX, 0x594, 1, 0x0000047C},
+ {L4CORE_INDEX, 0x5A4, 1, 0x00000480},
+ {L4CORE_INDEX, 0x5B4, 1, 0x00000484},
+ {L4CORE_INDEX, 0x5C4, 1, 0x00000488},
+ {L4CORE_INDEX, 0x5D4, 1, 0x0000048C},
+ {L4CORE_INDEX, 0x5DC, 1, 0x00000490},
+ {L4CORE_INDEX, 0x5E4, 1, 0x00000494},
+ {L4CORE_INDEX, 0x5EC, 1, 0x00000498},
+ {L4CORE_INDEX, 0x5F4, 1, 0x0000049C},
+ {L4CORE_INDEX, 0x5FC, 1, 0x000004A0},
+};
+
+/*
+ * omap_sar_save :
+ * common routine to save the registers to SAR RAM with the
+ * given parameters
+ * @nb_regs - Number of registers to saved
+ * @sar_bank_offset - where to backup
+ * @sar_layout - constant table containing the backup info
+ */
+static void sar_save(u32 nb_regs, u32 sar_bank, const u32 sar_layout_table[][4])
+{
+ u32 reg_val, size, i, j;
+ void __iomem *reg_read_addr, *sar_wr_addr;
+
+ for (i = 0; i < nb_regs; i++) {
+ if (omap4_sar_modules[(sar_layout_table[i][MODULE_ADDR_IDX])]) {
+ size = sar_layout_table[i][MODULE_NB_REGS_IDX];
+ reg_read_addr =
+ omap4_sar_modules[sar_layout_table[i]
+ [MODULE_ADDR_IDX]]
+ + sar_layout_table[i][MODULE_OFFSET_IDX];
+ sar_wr_addr = sar_ram_base + sar_bank +
+ sar_layout_table[i][SAR_RAM_OFFSET_IDX];
+ for (j = 0; j < size; j++) {
+ reg_val = __raw_readl(reg_read_addr + j * 4);
+ __raw_writel(reg_val, sar_wr_addr + j * 4);
+ }
+ }
+ }
+}
+
+static void save_sar_bank3(void)
+{
+ struct clockdomain *l4_secure_clkdm;
+
+ /*
+ * Not supported on ES1.0 silicon
+ */
+ if (omap_rev() == OMAP4430_REV_ES1_0) {
+ WARN_ONCE(1, "omap4: SAR backup not supported on ES1.0 ..\n");
+ return;
+ }
+
+ l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
+ clkdm_wakeup(l4_secure_clkdm);
+
+ if (cpu_is_omap446x())
+ sar_save(ARRAY_SIZE(omap446x_sar_ram3_layout), SAR_BANK3_OFFSET,
+ omap446x_sar_ram3_layout);
+ else
+ sar_save(ARRAY_SIZE(omap443x_sar_ram3_layout), SAR_BANK3_OFFSET,
+ omap443x_sar_ram3_layout);
+
+ clkdm_allow_idle(l4_secure_clkdm);
+}
+
+static int omap4_sar_not_accessible(void)
+{
+ u32 usbhost_state, usbtll_state;
+
+ /*
+ * Make sure that USB host and TLL modules are not
+ * enabled before attempting to save the context
+ * registers, otherwise this will trigger an exception.
+ */
+ usbhost_state = omap4_cminst_read_inst_reg(OMAP4430_CM2_PARTITION,
+ OMAP4430_CM2_L3INIT_INST,
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET)
+ & (OMAP4430_STBYST_MASK | OMAP4430_IDLEST_MASK);
+
+ usbtll_state = omap4_cminst_read_inst_reg(OMAP4430_CM2_PARTITION,
+ OMAP4430_CM2_L3INIT_INST,
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET)
+ & OMAP4430_IDLEST_MASK;
+
+ if ((usbhost_state == (OMAP4430_STBYST_MASK | OMAP4430_IDLEST_MASK)) &&
+ (usbtll_state == (OMAP4430_IDLEST_MASK)))
+ return 0;
+ else
+ return -EBUSY;
+}
+
+ /*
+ * omap4_sar_save -
+ * Save the context to SAR_RAM1 and SAR_RAM2 as per
+ * omap4xxx_sar_ram1_layout and omap4xxx_sar_ram2_layout for the device OFF
+ * mode
+ */
+int omap4_sar_save(void)
+{
+ /*
+ * Not supported on ES1.0 silicon
+ */
+ if (omap_rev() == OMAP4430_REV_ES1_0) {
+ WARN_ONCE(1, "omap4: SAR backup not supported on ES1.0 ..\n");
+ return -ENODEV;
+ }
+
+ if (omap4_sar_not_accessible()) {
+ pr_debug("%s: USB SAR CNTX registers are not accessible!\n",
+ __func__);
+ return -EBUSY;
+ }
+
+ /*
+ * SAR bits and clocks needs to be enabled
+ */
+ clkdm_wakeup(l3init_clkdm);
+ pwrdm_enable_hdwr_sar(l3init_pwrdm);
+ clk_enable(usb_host_ck);
+ clk_enable(usb_tll_ck);
+
+ /* Save SAR BANK1 */
+ if (cpu_is_omap446x())
+ sar_save(ARRAY_SIZE(omap446x_sar_ram1_layout), SAR_BANK1_OFFSET,
+ omap446x_sar_ram1_layout);
+ else
+ sar_save(ARRAY_SIZE(omap443x_sar_ram1_layout), SAR_BANK1_OFFSET,
+ omap443x_sar_ram1_layout);
+
+ clk_disable(usb_host_ck);
+ clk_disable(usb_tll_ck);
+ pwrdm_disable_hdwr_sar(l3init_pwrdm);
+ clkdm_allow_idle(l3init_clkdm);
+
+ /* Save SAR BANK2 */
+ if (cpu_is_omap446x())
+ sar_save(ARRAY_SIZE(omap446x_sar_ram2_layout), SAR_BANK2_OFFSET,
+ omap446x_sar_ram2_layout);
+ else
+ sar_save(ARRAY_SIZE(omap443x_sar_ram2_layout), SAR_BANK2_OFFSET,
+ omap443x_sar_ram2_layout);
+
+ return 0;
+}
+
+/**
+ * omap4_sar_overwrite :
+ * This API overwrite some of the SAR locations as a special cases
+ * The register content to be saved can be the register value before
+ * going into OFF-mode or a value that is required on wake up. This means
+ * that the restored register value can be different from the last value
+ * of the register before going into OFF-mode
+ * - CM1 and CM2 configuration
+ * Bits 0 of the CM_SHADOW_FREQ_CONFIG1 regiser and the
+ * CM_SHADOW_FREQ_CONFIG2 register are self-clearing and must
+ * be set at restore time. Thus, these data must always be
+ * overwritten in the SAR RAM.
+ * - Because USBHOSTHS and USBTLL restore needs a particular
+ * sequencing, the software must overwrite data read from
+ * the following registers implied in phase2a and phase 2b
+ */
+void omap4_sar_overwrite(void)
+{
+ u32 val = 0;
+ u32 offset = 0;
+
+ if (cpu_is_omap446x())
+ offset = 0x04;
+
+ /* Overwriting Phase1 data to be restored */
+ /* CM2 MEMIF_CLKTRCTRL = SW_WKUP, before FREQ UPDATE */
+ __raw_writel(0x2, sar_ram_base + SAR_BANK1_OFFSET + 0xd0);
+ /* CM1 CM_SHADOW_FREQ_CONFIG2, Enable FREQ UPDATE */
+ val = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG2);
+ /*
+ * FIXME: Implement FREQ UPDATE for L#/M5 before enabling this
+ * val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
+ */
+ __raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x100);
+ /* CM1 CM_SHADOW_FREQ_CONFIG1, Enable FREQ UPDATE */
+ val = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1);
+ val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
+ val &= ~OMAP4430_DLL_OVERRIDE_MASK;
+ __raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x104);
+ /* CM2 MEMIF_CLKTRCTRL = HW_AUTO, after FREQ UPDATE */
+ __raw_writel(0x3, sar_ram_base + SAR_BANK1_OFFSET + 0x124);
+
+ /* Overwriting Phase2a data to be restored */
+ /* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 1, MODULEMODE = 2 */
+ __raw_writel(0x00000012,
+ sar_ram_base + SAR_BANK1_OFFSET + 0x2ec + offset);
+ /* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 1, MODULEMODE = 1 */
+ __raw_writel(0x00000011,
+ sar_ram_base + SAR_BANK1_OFFSET + 0x2f0 + offset);
+ /* CM2 CM_SDMA_STATICDEP : Enable static depedency for SAR modules */
+ __raw_writel(0x000090e8,
+ sar_ram_base + SAR_BANK1_OFFSET + 0x2f4 + offset);
+
+ /* Overwriting Phase2b data to be restored */
+ /* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
+ val = __raw_readl(OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL);
+ val &= (OMAP4430_CLKSEL_UTMI_P1_MASK | OMAP4430_CLKSEL_UTMI_P2_MASK);
+ __raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x91c + offset);
+ /* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
+ __raw_writel(0x0000000,
+ sar_ram_base + SAR_BANK1_OFFSET + 0x920 + offset);
+ /* CM2 CM_SDMA_STATICDEP : Clear the static depedency */
+ __raw_writel(0x00000040,
+ sar_ram_base + SAR_BANK1_OFFSET + 0x924 + offset);
+
+ /* readback to ensure data reaches to SAR RAM */
+ barrier();
+ val = __raw_readl(sar_ram_base + SAR_BANK1_OFFSET + 0x924 + offset);
+}
+
+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 Actual SAR area used is 8K it's
+ * spaced over 16K address with some part is reserved.
+ */
+ sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+ BUG_ON(!sar_ram_base);
+
+ /*
+ * All these are static mappings so ioremap() will
+ * just return with mapped VA
+ */
+ omap4_sar_modules[EMIF1_INDEX] = ioremap(OMAP44XX_EMIF1, SZ_1M);
+ BUG_ON(!omap4_sar_modules[EMIF1_INDEX]);
+ omap4_sar_modules[EMIF2_INDEX] = ioremap(OMAP44XX_EMIF2, SZ_1M);
+ BUG_ON(!omap4_sar_modules[EMIF2_INDEX]);
+ omap4_sar_modules[DMM_INDEX] = ioremap(OMAP44XX_DMM_BASE, SZ_1M);
+ BUG_ON(!omap4_sar_modules[DMM_INDEX]);
+ omap4_sar_modules[CM1_INDEX] = ioremap(OMAP4430_CM1_BASE, SZ_8K);
+ BUG_ON(!omap4_sar_modules[CM1_INDEX]);
+ omap4_sar_modules[CM2_INDEX] = ioremap(OMAP4430_CM2_BASE, SZ_8K);
+ BUG_ON(!omap4_sar_modules[CM2_INDEX]);
+ omap4_sar_modules[C2C_INDEX] = ioremap(OMAP44XX_C2C_BASE, SZ_1M);
+ BUG_ON(!omap4_sar_modules[C2C_INDEX]);
+ omap4_sar_modules[CTRL_MODULE_PAD_CORE_INDEX] =
+ ioremap(OMAP443X_CTRL_BASE, SZ_4K);
+ BUG_ON(!omap4_sar_modules[CTRL_MODULE_PAD_CORE_INDEX]);
+ omap4_sar_modules[L3_CLK1_INDEX] = ioremap(L3_44XX_BASE_CLK1, SZ_1M);
+ BUG_ON(!omap4_sar_modules[L3_CLK1_INDEX]);
+ omap4_sar_modules[L3_CLK2_INDEX] = ioremap(L3_44XX_BASE_CLK2, SZ_1M);
+ BUG_ON(!omap4_sar_modules[L3_CLK2_INDEX]);
+ omap4_sar_modules[L3_CLK3_INDEX] = ioremap(L3_44XX_BASE_CLK3, SZ_1M);
+ BUG_ON(!omap4_sar_modules[L3_CLK3_INDEX]);
+ omap4_sar_modules[USBTLL_INDEX] = ioremap(OMAP44XX_USBTLL_BASE, SZ_1M);
+ BUG_ON(!omap4_sar_modules[USBTLL_INDEX]);
+ omap4_sar_modules[UHH_INDEX] = ioremap(OMAP44XX_UHH_CONFIG_BASE, SZ_1M);
+ BUG_ON(!omap4_sar_modules[UHH_INDEX]);
+ omap4_sar_modules[L4CORE_INDEX] = ioremap(L4_44XX_PHYS, SZ_4M);
+ BUG_ON(!omap4_sar_modules[L4CORE_INDEX]);
+ omap4_sar_modules[L4PER_INDEX] = ioremap(L4_PER_44XX_PHYS, SZ_4M);
+ BUG_ON(!omap4_sar_modules[L4PER_INDEX]);
+
+ /*
+ * SAR BANK3 contains all firewall settings and it's saved through
+ * secure API on HS device. On GP device these registers are
+ * meaningless but still needs to be saved. Otherwise Auto-restore
+ * phase DMA takes an abort. Hence save these conents only once
+ * in init to avoid the issue while waking up from device OFF
+ */
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP)
+ save_sar_bank3();
+ /*
+ * Work around for OMAP443x Errata i632: "LPDDR2 Corruption After OFF
+ * Mode Transition When CS1 Is Used On EMIF":
+ * Overwrite EMIF1/EMIF2
+ * SECURE_EMIF1_SDRAM_CONFIG2_REG
+ * SECURE_EMIF2_SDRAM_CONFIG2_REG
+ */
+ if (cpu_is_omap443x()) {
+ void __iomem *secure_ctrl_mod;
+
+ secure_ctrl_mod = ioremap(OMAP4_CTRL_MODULE_WKUP, SZ_4K);
+ BUG_ON(!secure_ctrl_mod);
+
+ __raw_writel(0x10, secure_ctrl_mod +
+ OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG);
+ __raw_writel(0x10, secure_ctrl_mod +
+ OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG);
+ wmb();
+ iounmap(secure_ctrl_mod);
+ }
+
+ /*
+ * L3INIT PD and clocks are needed for SAR save phase
+ */
+ l3init_pwrdm = pwrdm_lookup("l3init_pwrdm");
+ if (!l3init_pwrdm)
+ pr_err("Failed to get l3init_pwrdm\n");
+
+ l3init_clkdm = clkdm_lookup("l3_init_clkdm");
+ if (!l3init_clkdm)
+ pr_err("Failed to get l3_init_clkdm\n");
+
+ usb_host_ck = clk_get(NULL, "usb_host_hs_fck");
+ if (!usb_host_ck)
+ pr_err("Could not get usb_host_ck\n");
+
+ usb_tll_ck = clk_get(NULL, "usb_tll_hs_ick");
+ if (!usb_tll_ck)
+ pr_err("Could not get usb_tll_ck\n");
+
+ return 0;
+}
+early_initcall(omap4_sar_ram_init);
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..dd96726
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4_trim_quirks.c
@@ -0,0 +1,180 @@
+/*
+ * 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"
+#include "pm.h"
+#include <mach/ctrl_module_core_44xx.h>
+
+#define OMAP4_DPLL_MPU_TRIMMED_VAL_2P4 (0x1 << 18)
+#define OMAP4_DPLL_MPU_TRIMMED_VAL_3P0 (0x3 << 18)
+#define OMAP4_DPLL_MPU_TRIMMED_MASK (BIT(19) | BIT(18))
+/*
+ * Trim value has to be written to CONTROL_EFUSE_2 according to
+ * OMAP4430 errata i684 (version B)
+ * OMAP4430 units with ProdID[51:50]=11 are not affected
+ */
+#define OMAP4_LPDDR2_I684_FIX_VALUE 0x004E4000
+#define OMAP4_PROD_ID_I684_MASK 0x000C0000
+
+
+static bool bgap_trim_sw_overide;
+static bool dpll_trim_override;
+static bool ddr_io_trim_override;
+
+/**
+ * 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.
+ */
+int omap4_ldo_trim_configure(void)
+{
+ u32 val;
+
+ /* if not trimmed, we set force overide, insted of efuse. */
+ if (bgap_trim_sw_overide) {
+ /* 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);
+ }
+
+ /* For all trimmed and untrimmed write value as per recomendation */
+ val = 0x10 << OMAP4_AVDAC_TRIM_BYTE0_SHIFT;
+ val |= 0x01 << OMAP4_AVDAC_TRIM_BYTE1_SHIFT;
+ val |= 0x4d << OMAP4_AVDAC_TRIM_BYTE2_SHIFT;
+ val |= 0x1C << OMAP4_AVDAC_TRIM_BYTE3_SHIFT;
+ omap4_ctrl_pad_writel(val,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1);
+
+ /* DDR I/O Trim override as per erratum i684 */
+ if (ddr_io_trim_override) {
+ omap4_ctrl_pad_writel(OMAP4_LPDDR2_I684_FIX_VALUE,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2);
+ }
+
+ /* Required for DPLL_MPU to lock at 2.4 GHz */
+ if (dpll_trim_override)
+ omap_ctrl_writel(0x29, OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0);
+
+ return 0;
+}
+
+/**
+ * omap4460_mpu_dpll_trim_override() - provide a selective s/w trim overide
+ */
+static __init void omap4460_mpu_dpll_trim_override(void)
+{
+ u32 val;
+
+ val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1) &
+ OMAP4_DPLL_MPU_TRIMMED_MASK;
+ switch (val) {
+ case OMAP4_DPLL_MPU_TRIMMED_VAL_3P0:
+ /* all ok.. */
+ break;
+ case OMAP4_DPLL_MPU_TRIMMED_VAL_2P4:
+ /* Cross check! */
+ if (omap4_has_mpu_1_5ghz()) {
+ WARN(1, "%s: OMAP is 1.5GHz capable, trimmed=1.2GHz!\n",
+ __func__);
+ }
+ break;
+ default:
+ WARN(1, "%s: UNKNOWN TRIM:0x%08x, using s/w override\n",
+ __func__, val);
+ /* fall through and use override */
+ case 0:
+ /*
+ * For PRE_RTP devices: Not trimmed, use s/w override!
+ * We only support unto 1.2GHz with s/w override,
+ * so just give a gentle warning if higher opp is attempted
+ */
+ dpll_trim_override = true;
+ /* Confirm */
+ if (omap4_has_mpu_1_5ghz()) {
+ pr_err("%s: OMAP is 1.5GHz capable, s/w trim=1.2GHz!\n",
+ __func__);
+ }
+ break;
+ }
+}
+
+static __init int omap4_ldo_trim_init(void)
+{
+ u32 bgap_trimmed = 0;
+
+ /* 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)
+ bgap_trimmed = omap_ctrl_readl(
+ OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP);
+
+ bgap_trimmed &= OMAP4_STD_FUSE_OPP_BGAP_MASK_LSB;
+
+ /* if not trimmed, we set force overide, insted of efuse. */
+ if (!bgap_trimmed)
+ bgap_trim_sw_overide = true;
+
+ /* If not already trimmed, use s/w override */
+ if (cpu_is_omap446x())
+ omap4460_mpu_dpll_trim_override();
+
+ /*
+ * Errata i684 (revision B)
+ * Impacts all OMAP4430ESx.y trimmed and untrimmed excluding units
+ * with with ProdID[51:50]=11
+ * OMAP4460/70 are not impacted.
+ *
+ * ProdID:
+ * 51 50
+ * 0 0 Incorrect trim, SW WA needed.
+ * 0 1 Fixed test program issue of overlapping of LPDDR & SmartIO
+ * efuse fields, SW WA needed for LPDDR.
+ * 1 1 New LPDDR trim formula to compensate for vertical vs horizontal
+ * cell layout. No overwrite required.
+ */
+ if (cpu_is_omap443x()) {
+ u32 prod_id;
+
+ prod_id = omap_ctrl_readl(
+ OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
+ prod_id &= OMAP4_PROD_ID_I684_MASK;
+ if (prod_id != OMAP4_PROD_ID_I684_MASK)
+ ddr_io_trim_override = true;
+ }
+
+ return omap4_ldo_trim_configure();
+}
+arch_initcall(omap4_ldo_trim_init);
diff --git a/arch/arm/mach-omap2/omap_dmm.c b/arch/arm/mach-omap2/omap_dmm.c
new file mode 100644
index 0000000..c2c44d2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_dmm.c
@@ -0,0 +1,73 @@
+/*
+ * DMM driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <mach/dmm.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <mach/dmm.h>
+#include <mach/tiler.h>
+
+#ifdef CONFIG_TI_TILER
+
+static struct omap_dmm_platform_data dmm_data = {
+ .oh_name = "dmm",
+};
+
+static struct platform_device omap_tiler_device = {
+ .name = "tiler",
+ .id = -1,
+};
+
+static struct omap_device_pm_latency omap_dmm_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+
+void __init omap_dmm_init(void)
+{
+ struct omap_hwmod *oh = NULL;
+ struct omap_device *od = NULL;
+
+ oh = omap_hwmod_lookup(dmm_data.oh_name);
+ if (!oh)
+ return;
+
+ dmm_data.base = omap_hwmod_get_mpu_rt_va(oh);
+ dmm_data.irq = oh->mpu_irqs[0].irq;
+
+ od = omap_device_build(dmm_data.oh_name, -1, oh, &dmm_data,
+ sizeof(dmm_data), omap_dmm_latency,
+ ARRAY_SIZE(omap_dmm_latency), false);
+
+ /* register tiler platform device to go along with the dmm device */
+ if (platform_device_register(&omap_tiler_device) < 0)
+ printk(KERN_ERR "Unable to register OMAP Tiler device\n");
+
+ return;
+}
+
+#else
+void __init omap_dmm_init(void)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap2/omap_fiq_debugger.c b/arch/arm/mach-omap2/omap_fiq_debugger.c
new file mode 100644
index 0000000..174bba0
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_fiq_debugger.c
@@ -0,0 +1,418 @@
+/*
+ * Serial Debugger Interface for Omap
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/serial_reg.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/stacktrace.h>
+#include <linux/uaccess.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+#include <plat/omap-serial.h>
+
+#include <asm/fiq_debugger.h>
+
+#include <mach/omap_fiq_debugger.h>
+#include <mach/system.h>
+
+#include "mux.h"
+
+struct omap_fiq_debugger {
+ struct fiq_debugger_pdata pdata;
+ struct platform_device *pdev;
+ void __iomem *debug_port_base;
+ bool suspended;
+ spinlock_t lock;
+ bool have_state;
+
+ /* uart state */
+ unsigned char lcr;
+ unsigned char fcr;
+ unsigned char efr;
+ unsigned char dll;
+ unsigned char dlh;
+ unsigned char mcr;
+ unsigned char ier;
+ unsigned char wer;
+};
+
+static struct omap_fiq_debugger *dbgs[OMAP_MAX_HSUART_PORTS];
+
+static inline struct omap_fiq_debugger *get_dbg(struct platform_device *pdev)
+{
+ struct fiq_debugger_pdata *pdata = dev_get_platdata(&pdev->dev);
+ return container_of(pdata, struct omap_fiq_debugger, pdata);
+}
+
+static inline void omap_write(struct omap_fiq_debugger *dbg,
+ unsigned int val, unsigned int off)
+{
+ __raw_writel(val, dbg->debug_port_base + off * 4);
+}
+
+static inline unsigned int omap_read(struct omap_fiq_debugger *dbg,
+ unsigned int off)
+{
+ return __raw_readl(dbg->debug_port_base + off * 4);
+}
+
+static void debug_omap_port_enable(struct platform_device *pdev)
+{
+ pm_runtime_get_sync(&pdev->dev);
+}
+
+static void debug_omap_port_disable(struct platform_device *pdev)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dbg->lock, flags);
+ if (!dbg->suspended) {
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+ } else {
+ pm_runtime_put_sync_suspend(&pdev->dev);
+ }
+ spin_unlock_irqrestore(&dbg->lock, flags);
+}
+
+static int debug_omap_port_resume(struct platform_device *pdev)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+
+ dbg->suspended = false;
+ barrier();
+ return 0;
+}
+
+static int debug_omap_port_suspend(struct platform_device *pdev)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+ unsigned long flags;
+
+ /* this will force the device to be idle'd now, in case it was
+ * autosuspended but timer has not yet run out.
+ */
+ spin_lock_irqsave(&dbg->lock, flags);
+ dbg->suspended = true;
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_put_sync_suspend(&pdev->dev);
+ spin_unlock_irqrestore(&dbg->lock, flags);
+
+ return 0;
+}
+
+/* mostly copied from drivers/tty/serial/omap-serial.c */
+static void omap_write_mdr1(struct omap_fiq_debugger *dbg, u8 mdr1)
+{
+ u8 timeout = 255;
+
+ if (!(cpu_is_omap34xx() || cpu_is_omap44xx())) {
+ omap_write(dbg, UART_OMAP_MDR1_DISABLE, UART_OMAP_MDR1);
+ return;
+ }
+
+ omap_write(dbg, mdr1, UART_OMAP_MDR1);
+ udelay(2);
+ omap_write(dbg, dbg->fcr | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR,
+ UART_FCR);
+
+ /*
+ * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+ * TX_FIFO_E bit is 1.
+ */
+ while (UART_LSR_THRE !=
+ (omap_read(dbg, UART_LSR) & (UART_LSR_THRE | UART_LSR_DR))) {
+ timeout--;
+ if (!timeout) {
+ /* Should *never* happen. we warn and carry on */
+ dev_crit(&dbg->pdev->dev, "Errata i202: timedout %x\n",
+ omap_read(dbg, UART_LSR));
+ break;
+ }
+ udelay(1);
+ }
+}
+
+/* assume the bootloader programmed us correctly */
+static void debug_port_read_state(struct omap_fiq_debugger *dbg)
+{
+ /* assume we're in operational mode when we are called */
+ dbg->lcr = omap_read(dbg, UART_LCR);
+
+ /* config mode A */
+ omap_write(dbg, UART_LCR_CONF_MODE_A, UART_LCR);
+ dbg->mcr = omap_read(dbg, UART_MCR);
+
+ /* config mode B */
+ omap_write(dbg, UART_LCR_CONF_MODE_B, UART_LCR);
+ dbg->efr = omap_read(dbg, UART_EFR);
+ dbg->dll = omap_read(dbg, UART_DLL);
+ dbg->dlh = omap_read(dbg, UART_DLM);
+
+ /* back to operational */
+ omap_write(dbg, dbg->lcr, UART_LCR);
+
+ pr_debug("%s: lcr=%02x mcr=%02x efr=%02x dll=%02x dlh=%02x\n",
+ __func__, dbg->lcr, dbg->mcr, dbg->efr, dbg->dll, dbg->dlh);
+}
+
+static void debug_port_restore(struct omap_fiq_debugger *dbg)
+{
+ omap_write(dbg, UART_LCR_CONF_MODE_B, UART_LCR); /* Config B mode */
+ omap_write(dbg, dbg->efr | UART_EFR_ECB, UART_EFR);
+ omap_write(dbg, 0x0, UART_LCR); /* Operational mode */
+ omap_write(dbg, 0x0, UART_IER);
+ omap_write(dbg, UART_LCR_CONF_MODE_B, UART_LCR); /* Config B mode */
+ omap_write(dbg, 0, UART_DLL);
+ omap_write(dbg, 0, UART_DLM);
+ omap_write(dbg, UART_LCR_CONF_MODE_A, UART_LCR);
+ omap_write(dbg, dbg->mcr | UART_MCR_TCRTLR, UART_MCR);
+ omap_write(dbg, UART_LCR_CONF_MODE_B, UART_LCR);
+ omap_write(dbg, 0, UART_TI752_TLR);
+ omap_write(dbg, 0, UART_SCR);
+ omap_write(dbg, dbg->efr, UART_EFR);
+ omap_write(dbg, UART_LCR_CONF_MODE_A, UART_LCR);
+ omap_write(dbg, dbg->fcr, UART_FCR);
+ omap_write(dbg, dbg->mcr, UART_MCR);
+ omap_write_mdr1(dbg, UART_OMAP_MDR1_DISABLE);
+
+ omap_write(dbg, UART_LCR_CONF_MODE_B, UART_LCR);
+ omap_write(dbg, dbg->efr | UART_EFR_ECB, UART_EFR);
+ omap_write(dbg, dbg->dll, UART_DLL);
+ omap_write(dbg, dbg->dlh, UART_DLM);
+ omap_write(dbg, 0, UART_LCR);
+ omap_write(dbg, dbg->ier, UART_IER);
+ omap_write(dbg, UART_LCR_CONF_MODE_B, UART_LCR);
+ omap_write(dbg, dbg->efr, UART_EFR);
+
+ /* will put us back to operational mode */
+ omap_write(dbg, dbg->lcr, UART_LCR);
+ omap_write_mdr1(dbg, UART_OMAP_MDR1_16X_MODE);
+
+ omap_write(dbg, dbg->wer, UART_OMAP_WER);
+}
+
+u32 omap_debug_uart_resume_idle(void)
+{
+ int i;
+ u32 ret = 0;
+
+ for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+ struct omap_fiq_debugger *dbg = dbgs[i];
+ struct omap_device *od;
+
+ if (!dbg || !dbg->pdev)
+ continue;
+
+ od = to_omap_device(dbg->pdev);
+ if (omap_hwmod_pad_get_wakeup_status(od->hwmods[0])) {
+ /*
+ * poke the uart and let it stay on long enough
+ * to process any further data. It's ok to use
+ * autosuspend here since this is on the resume path
+ * during the wakeup. We'll still go through a full
+ * resume cycle, so if we go back to suspend
+ * the suspended flag will properly get reset.
+ */
+ pm_runtime_get_sync(&dbg->pdev->dev);
+ pm_runtime_mark_last_busy(&dbg->pdev->dev);
+ pm_runtime_put_autosuspend(&dbg->pdev->dev);
+ dev_dbg(&dbg->pdev->dev, "woke up from IO pad\n");
+ ret++;
+ }
+ }
+
+ return ret;
+}
+
+static int debug_port_init(struct platform_device *pdev)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+
+ dbg->ier = UART_IER_RLSI | UART_IER_RDI;
+ dbg->fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_01;
+ dbg->wer = 0;
+
+ device_init_wakeup(&pdev->dev, true);
+
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DEFAULT_AUTOSUSPEND_DELAY);
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_irq_safe(&pdev->dev);
+
+ omap_hwmod_idle(to_omap_device(pdev)->hwmods[0]);
+ debug_omap_port_enable(pdev);
+ debug_omap_port_disable(pdev);
+
+ debug_omap_port_enable(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ omap_hwmod_enable_wakeup(to_omap_device(pdev)->hwmods[0]);
+
+ debug_port_read_state(dbg);
+ debug_port_restore(dbg);
+
+ dbg->have_state = true;
+
+
+ debug_omap_port_disable(pdev);
+ return 0;
+}
+
+static int debug_getc(struct platform_device *pdev)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+ unsigned int lsr;
+ int ret = FIQ_DEBUGGER_NO_CHAR;
+
+ lsr = omap_read(dbg, UART_LSR);
+ if (lsr & UART_LSR_BI) {
+ /* need to read RHR to clear the BI condition */
+ omap_read(dbg, UART_RX);
+ ret = FIQ_DEBUGGER_BREAK;
+ } else if (lsr & UART_LSR_DR) {
+ ret = omap_read(dbg, UART_RX);
+ }
+
+ return ret;
+}
+
+static void debug_putc(struct platform_device *pdev, unsigned int c)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+
+ while (!(omap_read(dbg, UART_LSR) & UART_LSR_THRE))
+ cpu_relax();
+
+ omap_write(dbg, c, UART_TX);
+}
+
+static void debug_flush(struct platform_device *pdev)
+{
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+
+ while (!(omap_read(dbg, UART_LSR) & UART_LSR_TEMT))
+ cpu_relax();
+}
+
+static int uart_idle_hwmod(struct omap_device *od)
+{
+ omap_hwmod_idle(od->hwmods[0]);
+
+ return 0;
+}
+
+static int uart_enable_hwmod(struct omap_device *od)
+{
+ struct platform_device *pdev = &od->pdev;
+ struct omap_fiq_debugger *dbg = get_dbg(pdev);
+
+ omap_hwmod_enable(od->hwmods[0]);
+ if (omap_pm_was_context_lost(&pdev->dev) && dbg->have_state) {
+ debug_port_restore(dbg);
+ dev_dbg(&pdev->dev, "restoring lost context!\n");
+ }
+
+ return 0;
+}
+
+static struct omap_device_pm_latency omap_uart_latency[] = {
+ {
+ .deactivate_func = uart_idle_hwmod,
+ .activate_func = uart_enable_hwmod,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+extern struct omap_hwmod *omap_uart_hwmod_lookup(int num);
+
+int __init omap_serial_debug_init(int id, bool is_fiq, bool is_high_prio_irq,
+ struct omap_device_pad *pads, int num_pads)
+{
+ struct omap_fiq_debugger *dbg;
+ struct omap_hwmod *oh;
+ struct omap_device *od;
+ int ret;
+
+ if (id >= OMAP_MAX_HSUART_PORTS)
+ return -EINVAL;
+ if (dbgs[id])
+ return -EBUSY;
+
+ oh = omap_uart_hwmod_lookup(id);
+ if (!oh)
+ return -ENODEV;
+
+ oh->mpu_irqs[0].name = "uart_irq";
+ oh->mux = omap_hwmod_mux_init(pads, num_pads);
+
+ dbg = kzalloc(sizeof(struct omap_fiq_debugger), GFP_KERNEL);
+ if (!dbg) {
+ pr_err("Failed to allocate for fiq debugger\n");
+ return -ENOMEM;
+ }
+
+ dbg->debug_port_base = ioremap(oh->slaves[0]->addr[0].pa_start,
+ PAGE_SIZE);
+ if (!dbg->debug_port_base) {
+ pr_err("Failed to ioremap for fiq debugger\n");
+ ret = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ spin_lock_init(&dbg->lock);
+
+ dbg->pdata.uart_init = debug_port_init;
+ dbg->pdata.uart_getc = debug_getc;
+ dbg->pdata.uart_putc = debug_putc;
+ dbg->pdata.uart_flush = debug_flush;
+ dbg->pdata.uart_enable = debug_omap_port_enable;
+ dbg->pdata.uart_disable = debug_omap_port_disable;
+ dbg->pdata.uart_dev_suspend = debug_omap_port_suspend;
+ dbg->pdata.uart_dev_resume = debug_omap_port_resume;
+
+ od = omap_device_build("fiq_debugger", id,
+ oh, dbg, sizeof(*dbg), omap_uart_latency,
+ ARRAY_SIZE(omap_uart_latency), false);
+ if (IS_ERR(od)) {
+ pr_err("Could not build omap_device for fiq_debugger: %s\n",
+ oh->name);
+ ret = PTR_ERR(od);
+ goto err_dev_build;
+ }
+
+ dbg->pdev = &od->pdev;
+ dbgs[id] = dbg;
+
+ return 0;
+
+err_dev_build:
+ iounmap(dbg->debug_port_base);
+err_ioremap:
+ kfree(dbg);
+ return ret;
+}
diff --git a/arch/arm/mach-omap2/omap_hsi.c b/arch/arm/mach-omap2/omap_hsi.c
new file mode 100644
index 0000000..ce8fa54
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hsi.c
@@ -0,0 +1,426 @@
+/*
+ * arch/arm/mach-omap2/hsi.c
+ *
+ * HSI device definition
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Original Author: Sebastien JAN <s-jan@ti.com>
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/notifier.h>
+#include <linux/hsi_driver_if.h>
+
+#include <asm/clkdev.h>
+
+#include <plat/omap_hsi.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+
+#include <../drivers/omap_hsi/hsi_driver.h>
+#include "clock.h"
+#include "mux.h"
+#include "control.h"
+
+static int omap_hsi_wakeup_enable(int hsi_port);
+static int omap_hsi_wakeup_disable(int hsi_port);
+#define OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME "omap_hsi"
+#define OMAP_HSI_PLATFORM_DEVICE_NAME "omap_hsi.0"
+#define OMAP_HSI_HWMOD_NAME "hsi"
+#define OMAP_HSI_HWMOD_CLASSNAME "hsi"
+#define OMAP_HSI_PADCONF_CAWAKE_PIN "usbb1_ulpitll_clk.hsi1_cawake"
+#define OMAP_HSI_PADCONF_CAWAKE_MODE OMAP_MUX_MODE1
+
+
+#define OMAP_MUX_MODE_MASK 0x7
+
+
+/* Hack till correct hwmod-mux api gets used */
+#define CA_WAKE_MUX_REG (0x4a1000C2)
+#define OMAP44XX_PADCONF_WAKEUPENABLE0 (1 << 14)
+#define OMAP44XX_PADCONF_WAKEUPEVENT0 (1 << 15)
+
+static int omap_mux_read_signal(const char *muxname)
+{
+ u16 val = 0;
+ val = omap_readw(CA_WAKE_MUX_REG);
+ return val;
+}
+
+static int omap_mux_enable_wakeup(const char *muxname)
+{
+ u16 val = 0;
+ val = omap_readw(CA_WAKE_MUX_REG);
+ val |= OMAP44XX_PADCONF_WAKEUPENABLE0;
+ omap_writew(val, CA_WAKE_MUX_REG);
+ return 0;
+}
+
+static int omap_mux_disable_wakeup(const char *muxname)
+{
+ u16 val = 0;
+ val = omap_readw(CA_WAKE_MUX_REG);
+ val &= ~OMAP44XX_PADCONF_WAKEUPENABLE0;
+ omap_writew(val, CA_WAKE_MUX_REG);
+ return 0;
+}
+
+/*
+ * NOTE: We abuse a little bit the struct port_ctx to use it also for
+ * initialization.
+ */
+
+
+static struct port_ctx hsi_port_ctx[] = {
+ [0] = {
+ .hst.mode = HSI_MODE_FRAME,
+ .hst.flow = HSI_FLOW_SYNCHRONIZED,
+ .hst.frame_size = HSI_FRAMESIZE_DEFAULT,
+ .hst.divisor = HSI_DIVISOR_DEFAULT,
+ .hst.channels = HSI_CHANNELS_DEFAULT,
+ .hst.arb_mode = HSI_ARBMODE_ROUNDROBIN,
+ .hsr.mode = HSI_MODE_FRAME,
+ .hsr.flow = HSI_FLOW_SYNCHRONIZED,
+ .hsr.frame_size = HSI_FRAMESIZE_DEFAULT,
+ .hsr.channels = HSI_CHANNELS_DEFAULT,
+ .hsr.divisor = HSI_DIVISOR_DEFAULT,
+ .hsr.counters = HSI_COUNTERS_FT_DEFAULT |
+ HSI_COUNTERS_TB_DEFAULT |
+ HSI_COUNTERS_FB_DEFAULT,
+ },
+};
+
+static struct ctrl_ctx hsi_ctx = {
+ .sysconfig = 0,
+ .gdd_gcr = 0,
+ .dll = 0,
+ .pctx = hsi_port_ctx,
+};
+
+static struct hsi_platform_data omap_hsi_platform_data = {
+ .num_ports = ARRAY_SIZE(hsi_port_ctx),
+ .hsi_gdd_chan_count = HSI_HSI_DMA_CHANNEL_MAX,
+ .default_hsi_fclk = HSI_DEFAULT_FCLK,
+ .ctx = &hsi_ctx,
+ .device_enable = omap_device_enable,
+ .device_idle = omap_device_idle,
+ .device_shutdown = omap_device_shutdown,
+ .wakeup_enable = omap_hsi_wakeup_enable,
+ .wakeup_disable = omap_hsi_wakeup_disable,
+ .wakeup_is_from_hsi = omap_hsi_is_io_wakeup_from_hsi,
+ .board_suspend = omap_hsi_prepare_suspend,
+};
+
+
+static struct platform_device *hsi_get_hsi_platform_device(void)
+{
+ struct device *dev;
+ struct platform_device *pdev;
+
+ /* HSI_TODO: handle platform device id (or port) (0/1) */
+ dev = bus_find_device_by_name(&platform_bus_type, NULL,
+ OMAP_HSI_PLATFORM_DEVICE_NAME);
+ if (!dev) {
+ pr_debug("Could not find platform device %s\n",
+ OMAP_HSI_PLATFORM_DEVICE_NAME);
+ return 0;
+ }
+
+ if (!dev->driver) {
+ /* Could not find driver for platform device. */
+ return 0;
+ }
+
+ pdev = to_platform_device(dev);
+
+ return pdev;
+}
+
+static struct hsi_dev *hsi_get_hsi_controller_data(struct platform_device *pd)
+{
+ struct hsi_dev *hsi_ctrl;
+
+ if (!pd)
+ return 0;
+
+ hsi_ctrl = (struct hsi_dev *) platform_get_drvdata(pd);
+ if (!hsi_ctrl) {
+ pr_err("Could not find HSI controller data\n");
+ return 0;
+ }
+
+ return hsi_ctrl;
+}
+
+/**
+* omap_hsi_is_io_pad_hsi - Indicates if IO Pad has been muxed for HSI CAWAKE
+*
+* Return value :* 0 if CAWAKE Padconf has not been found or CAWAKE not muxed for
+* CAWAKE
+* * else 1
+*/
+static int omap_hsi_is_io_pad_hsi(void)
+{
+ u16 val;
+
+ /* Check for IO pad */
+ val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ if (val == -ENODEV)
+ return 0;
+
+ /* Continue only if CAWAKE is muxed */
+ if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
+ return 0;
+
+ return 1;
+}
+
+/**
+* omap_hsi_is_io_wakeup_from_hsi - Indicates an IO wakeup from HSI CAWAKE
+*
+* Return value :* 0 if CAWAKE Padconf has not been found or no IOWAKEUP event
+* occured for CAWAKE
+* * else 1
+* TODO : return value should indicate the HSI port which has awaken
+*/
+int omap_hsi_is_io_wakeup_from_hsi(void)
+{
+ u16 val;
+
+ /* Check for IO pad wakeup */
+ val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ if (val == -ENODEV)
+ return 0;
+
+ /* Continue only if CAWAKE is muxed */
+ if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
+ return 0;
+
+ if (val & OMAP44XX_PADCONF_WAKEUPEVENT0)
+ return 1;
+
+ return 0;
+}
+
+/**
+* omap_hsi_wakeup_enable - Enable HSI wakeup feature from RET/OFF mode
+*
+* @hsi_port - reference to the HSI port onto which enable wakeup feature.
+*
+* Return value :* 0 if CAWAKE has been configured to wakeup platform
+* * -ENODEV if CAWAKE is not muxed on padconf
+*/
+static int omap_hsi_wakeup_enable(int hsi_port)
+{
+ int ret = -ENODEV;
+
+ if (omap_hsi_is_io_pad_hsi())
+ ret = omap_mux_enable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ else
+ pr_debug("Trying to enable HSI IO wakeup on non HSI board\n");
+
+
+ /* TODO: handle hsi_port param and use it to find the correct Pad */
+ return ret;
+}
+
+/**
+* omap_hsi_wakeup_disable - Disable HSI wakeup feature from RET/OFF mode
+*
+* @hsi_port - reference to the HSI port onto which disable wakeup feature.
+*
+* Return value :* 0 if CAWAKE has been configured to not wakeup platform
+* * -ENODEV if CAWAKE is not muxed on padconf
+*/
+static int omap_hsi_wakeup_disable(int hsi_port)
+{
+ int ret = -ENODEV;
+
+ if (omap_hsi_is_io_pad_hsi())
+ ret = omap_mux_disable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ else
+ pr_debug("Trying to disable HSI IO wakeup on non HSI board\n");
+
+
+ /* TODO: handle hsi_port param and use it to find the correct Pad */
+
+ return ret;
+}
+
+/**
+* omap_hsi_prepare_suspend - Prepare HSI for suspend mode
+*
+* Return value :* 0 if CAWAKE padconf has been configured properly
+* * -ENODEV if CAWAKE is not muxed on padconf.
+*
+*/
+int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup)
+{
+ int ret;
+
+ if (dev_may_wakeup)
+ ret = omap_hsi_wakeup_enable(hsi_port);
+ else
+ ret = omap_hsi_wakeup_disable(hsi_port);
+
+ return ret;
+}
+
+/**
+* omap_hsi_wakeup - Prepare HSI for wakeup from suspend mode (RET/OFF)
+*
+* Return value : 1 if IO wakeup source is HSI
+* 0 if IO wakeup source is not HSI.
+*/
+int omap_hsi_wakeup(int hsi_port)
+{
+ static struct platform_device *pdev;
+ static struct hsi_dev *hsi_ctrl;
+
+ if (!pdev) {
+ pdev = hsi_get_hsi_platform_device();
+ if (!pdev)
+ return -ENODEV;
+}
+
+ if (!device_may_wakeup(&pdev->dev)) {
+ dev_info(&pdev->dev, "Modem not allowed to wakeup platform");
+ return -EPERM;
+ }
+
+ if (!hsi_ctrl) {
+ hsi_ctrl = hsi_get_hsi_controller_data(pdev);
+ if (!hsi_ctrl)
+ return -ENODEV;
+ }
+
+ dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad");
+
+ /* CAWAKE falling or rising edge detected */
+ hsi_ctrl->hsi_port->cawake_off_event = true;
+ tasklet_hi_schedule(&hsi_ctrl->hsi_port->hsi_tasklet);
+
+ /* Disable interrupt until Bottom Half has cleared */
+ /* the IRQ status register */
+ disable_irq_nosync(hsi_ctrl->hsi_port->irq);
+
+ return 0;
+}
+
+/* HSI_TODO : This requires some fine tuning & completion of
+ * activate/deactivate latency values
+ */
+static struct omap_device_pm_latency omap_hsi_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+/* HSI device registration */
+static int __init omap_hsi_register(struct omap_hwmod *oh, void *user)
+{
+ struct omap_device *od;
+ struct hsi_platform_data *pdata = &omap_hsi_platform_data;
+
+ if (!oh) {
+ pr_err("Could not look up %s omap_hwmod\n",
+ OMAP_HSI_HWMOD_NAME);
+ return -EEXIST;
+ }
+
+ od = omap_device_build(OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, 0, oh,
+ pdata, sizeof(*pdata), omap_hsi_latency,
+ ARRAY_SIZE(omap_hsi_latency), false);
+ WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+ OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, oh->name);
+
+ pr_info("HSI: device registered as omap_hwmod: %s\n", oh->name);
+ return 0;
+}
+
+static void __init omap_4430hsi_pad_conf(void)
+{
+ /*
+ * HSI pad conf: hsi1_ca/ac_wake/flag/data/ready
+ * Also configure gpio_92/95/157/187 used by modem
+ */
+ /* hsi1_cawake */
+ omap_mux_init_signal("usbb1_ulpitll_clk.hsi1_cawake", \
+ OMAP_PIN_INPUT_PULLDOWN | \
+ OMAP_PIN_OFF_NONE | \
+ OMAP_PIN_OFF_WAKEUPENABLE);
+ /* hsi1_caflag */
+ omap_mux_init_signal("usbb1_ulpitll_dir.hsi1_caflag", \
+ OMAP_PIN_INPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_cadata */
+ omap_mux_init_signal("usbb1_ulpitll_stp.hsi1_cadata", \
+ OMAP_PIN_INPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_acready */
+ omap_mux_init_signal("usbb1_ulpitll_nxt.hsi1_acready", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_OUTPUT_LOW);
+ /* hsi1_acwake */
+ omap_mux_init_signal("usbb1_ulpitll_dat0.hsi1_acwake", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_acdata */
+ omap_mux_init_signal("usbb1_ulpitll_dat1.hsi1_acdata", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_acflag */
+ omap_mux_init_signal("usbb1_ulpitll_dat2.hsi1_acflag", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_caready */
+ omap_mux_init_signal("usbb1_ulpitll_dat3.hsi1_caready", \
+ OMAP_PIN_INPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* gpio_92 */
+ omap_mux_init_signal("usbb1_ulpitll_dat4.gpio_92", \
+ OMAP_PULL_ENA);
+ /* gpio_95 */
+ omap_mux_init_signal("usbb1_ulpitll_dat7.gpio_95", \
+ OMAP_PIN_INPUT_PULLDOWN | \
+ OMAP_PIN_OFF_NONE);
+ /* gpio_157 */
+ omap_mux_init_signal("usbb2_ulpitll_clk.gpio_157", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* gpio_187 */
+ omap_mux_init_signal("sys_boot3.gpio_187", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+}
+
+int __init omap_hsi_dev_init(void)
+{
+ /* Keep this for genericity, although there is only one hwmod for HSI */
+ return omap_hwmod_for_each_by_class(OMAP_HSI_HWMOD_CLASSNAME,
+ omap_hsi_register, NULL);
+}
+postcore_initcall(omap_hsi_dev_init);
+
+/* HSI devices registration */
+int __init omap_hsi_init(void)
+{
+ omap_4430hsi_pad_conf();
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6c..fac4aec 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -142,13 +142,16 @@
#include "powerdomain.h"
#include <plat/clock.h>
#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
#include <plat/prcm.h>
+#include <mach/emif.h>
#include "cm2xxx_3xxx.h"
#include "cm44xx.h"
#include "prm2xxx_3xxx.h"
#include "prm44xx.h"
#include "mux.h"
+#include "pm.h"
/* Maximum microseconds to wait for OMAP module to softreset */
#define MAX_MODULE_SOFTRESET_WAIT 10000
@@ -391,7 +394,8 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
if (!oh->class->sysc ||
!((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
- (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
+ (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
+ (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
return -EINVAL;
if (!oh->class->sysc->sysc_fields) {
@@ -401,10 +405,13 @@ 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);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
/* XXX test pwrdm_get_wken for this hwmod's subsystem */
@@ -426,7 +433,8 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
if (!oh->class->sysc ||
!((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
- (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
+ (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
+ (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
return -EINVAL;
if (!oh->class->sysc->sysc_fields) {
@@ -436,10 +444,13 @@ 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);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
/* XXX test pwrdm_get_wken for this hwmod's subsystem */
@@ -781,8 +792,16 @@ static void _enable_sysc(struct omap_hwmod *oh)
}
if (sf & SYSC_HAS_MIDLEMODE) {
- idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
- HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
+ if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+ idlemode = HWMOD_IDLEMODE_NO;
+ } else {
+ if (sf & SYSC_HAS_ENAWAKEUP)
+ _enable_wakeup(oh, &v);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+ else
+ idlemode = HWMOD_IDLEMODE_SMART;
+ }
_set_master_standbymode(oh, idlemode, &v);
}
@@ -840,8 +859,16 @@ static void _idle_sysc(struct omap_hwmod *oh)
}
if (sf & SYSC_HAS_MIDLEMODE) {
- idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
- HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART;
+ if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+ idlemode = HWMOD_IDLEMODE_FORCE;
+ } else {
+ if (sf & SYSC_HAS_ENAWAKEUP)
+ _enable_wakeup(oh, &v);
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+ else
+ idlemode = HWMOD_IDLEMODE_SMART;
+ }
_set_master_standbymode(oh, idlemode, &v);
}
@@ -1154,6 +1181,9 @@ static int _ocp_softreset(struct omap_hwmod *oh)
goto dis_opt_clks;
_write_sysconfig(v, oh);
+ if (oh->class->sysc->srst_udelay)
+ udelay(oh->class->sysc->srst_udelay);
+
if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
omap_test_timeout((omap_hwmod_read(oh,
oh->class->sysc->syss_offs)
@@ -1223,6 +1253,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 &&
@@ -1243,17 +1274,17 @@ static int _enable(struct omap_hwmod *oh)
oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
_deassert_hardreset(oh, oh->rst_lines[0].name);
- /* Mux pins for device runtime if populated */
- if (oh->mux && (!oh->mux->enabled ||
- ((oh->_state == _HWMOD_STATE_IDLE) &&
- oh->mux->pads_dynamic)))
- 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 */
@@ -1268,6 +1299,12 @@ static int _enable(struct omap_hwmod *oh)
oh->name, r);
}
+ /* Mux pins for device runtime if populated */
+ if (oh->mux && (!oh->mux->enabled ||
+ ((oh->_state == _HWMOD_STATE_ENABLED) &&
+ oh->mux->pads_dynamic)))
+ omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
+
return r;
}
@@ -1295,8 +1332,11 @@ static int _idle(struct omap_hwmod *oh)
_disable_clocks(oh);
/* Mux pins for device idle if populated */
- if (oh->mux && oh->mux->pads_dynamic)
+ if (oh->mux && oh->mux->pads_dynamic) {
omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+ if (cpu_is_omap44xx())
+ omap4_trigger_ioctrl();
+ }
oh->_state = _HWMOD_STATE_IDLE;
@@ -1374,8 +1414,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
@@ -1507,6 +1550,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
* that the copy process would be relatively complex due to the large number
* of substructures.
*/
+
static int __init _register(struct omap_hwmod *oh)
{
int ms_id;
@@ -1538,6 +1582,12 @@ static int __init _register(struct omap_hwmod *oh)
*/
if (!strcmp(oh->name, MPU_INITIATOR_NAME))
mpu_oh = oh;
+ else if (cpu_is_omap44xx()) {
+ if (!strcmp(oh->name, "emif1"))
+ emif_clear_irq(0);
+ else if (!strcmp(oh->name, "emif2"))
+ emif_clear_irq(1);
+ }
return 0;
}
@@ -1770,6 +1820,34 @@ static int __init omap_hwmod_setup_all(void)
core_initcall(omap_hwmod_setup_all);
/**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+ struct omap_device_pad *pad;
+ int ret = -EINVAL, j;
+
+ if (oh->mux && oh->mux->enabled) {
+ for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+ pad = oh->mux->pads_dynamic[j];
+ if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+ if (set_wake)
+ pad->idle |= OMAP_WAKEUP_EN;
+ else
+ pad->idle &= ~OMAP_WAKEUP_EN;
+ ret = 0;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
* omap_hwmod_enable - enable an omap_hwmod
* @oh: struct omap_hwmod *
*
@@ -2097,6 +2175,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
{
return _del_initiator_dep(oh, init_oh);
}
+/**
+ * omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * set wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh)
+{
+ /* Enable pad wake-up capability */
+ return omap_hwmod_set_ioring_wakeup(oh, true);
+}
+
+/**
+ * omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * clear wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
+{
+ /* Disable pad wakeup capability */
+ return omap_hwmod_set_ioring_wakeup(oh, false);
+}
/**
* omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2123,6 +2230,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
v = oh->_sysc_cache;
_enable_wakeup(oh, &v);
_write_sysconfig(v, oh);
+ omap_hwmod_enable_ioring_wakeup(oh);
spin_unlock_irqrestore(&oh->_lock, flags);
return 0;
@@ -2153,6 +2261,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
v = oh->_sysc_cache;
_disable_wakeup(oh, &v);
_write_sysconfig(v, oh);
+ omap_hwmod_disable_ioring_wakeup(oh);
spin_unlock_irqrestore(&oh->_lock, flags);
return 0;
@@ -2332,7 +2441,7 @@ ohsps_unlock:
* Returns the context loss count of the powerdomain assocated with @oh
* upon success, or zero if no powerdomain exists for @oh.
*/
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
{
struct powerdomain *pwrdm;
int ret = 0;
@@ -2369,3 +2478,42 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
return 0;
}
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+ if (oh && oh->mux)
+ return omap_hwmod_mux_get_wake_status(oh->mux);
+ return -EINVAL;
+}
+
+/**
+ * omap_hwmod_name_get_dev() - convert a hwmod name to device pointer
+ * @oh_name: name of the hwmod device
+ *
+ * returns back a struct device * pointer associated with a hwmod
+ * device represented by a hwmod_name
+ */
+struct device *omap_hwmod_name_get_dev(const char *oh_name)
+{
+ struct omap_hwmod *oh;
+
+ if (!oh_name) {
+ WARN(1, "%s: no hwmod name!\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ oh = _lookup(oh_name);
+ if (IS_ERR_OR_NULL(oh)) {
+ WARN(1, "%s: no hwmod for %s\n", __func__,
+ oh_name);
+ return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+ }
+ if (IS_ERR_OR_NULL(oh->od)) {
+ WARN(1, "%s: no omap_device for %s\n", __func__,
+ oh_name);
+ return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+ }
+
+ return &oh->od->pdev.dev;
+}
+EXPORT_SYMBOL(omap_hwmod_name_get_dev);
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index c4d0ae8..d87019d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1208,6 +1208,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
};
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss1_fck" },
{ .role = "tv_clk", .clk = "dss_54m_fck" },
{ .role = "sys_clk", .clk = "dss2_fck" },
};
@@ -1291,6 +1292,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
&omap2420_l4_core__dss_dispc,
};
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss1_fck" },
+};
+
static struct omap_hwmod omap2420_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap2420_dispc_hwmod_class,
@@ -1306,6 +1311,8 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
},
},
+ .opt_clks = dispc_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks),
.slaves = omap2420_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dss_dispc_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -1361,6 +1368,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
&omap2420_l4_core__dss_rfbi,
};
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+ { .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
.name = "dss_rfbi",
.class = &omap2420_rfbi_hwmod_class,
@@ -1372,6 +1383,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
.module_offs = CORE_MOD,
},
},
+ .opt_clks = rfbi_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks),
.slaves = omap2420_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dss_rfbi_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -1418,6 +1431,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
&omap2420_l4_core__dss_venc,
};
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+ { .role = "tv_clk", .clk = "dss_54m_fck" },
+};
+
static struct omap_hwmod omap2420_dss_venc_hwmod = {
.name = "dss_venc",
.class = &omap2420_venc_hwmod_class,
@@ -1429,6 +1446,8 @@ static struct omap_hwmod omap2420_dss_venc_hwmod = {
.module_offs = CORE_MOD,
},
},
+ .opt_clks = venc_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks),
.slaves = omap2420_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dss_venc_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 9682dd5..8009945 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1302,6 +1302,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
};
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss1_fck" },
{ .role = "tv_clk", .clk = "dss_54m_fck" },
{ .role = "sys_clk", .clk = "dss2_fck" },
};
@@ -1379,6 +1380,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
&omap2430_l4_core__dss_dispc,
};
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss1_fck" },
+};
+
static struct omap_hwmod omap2430_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap2430_dispc_hwmod_class,
@@ -1394,6 +1399,8 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
},
},
+ .opt_clks = dispc_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks),
.slaves = omap2430_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dss_dispc_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -1443,6 +1450,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
&omap2430_l4_core__dss_rfbi,
};
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+ { .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
.name = "dss_rfbi",
.class = &omap2430_rfbi_hwmod_class,
@@ -1454,6 +1465,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
.module_offs = CORE_MOD,
},
},
+ .opt_clks = rfbi_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks),
.slaves = omap2430_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dss_rfbi_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -1494,6 +1507,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
&omap2430_l4_core__dss_venc,
};
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+ { .role = "tv_clk", .clk = "dss_54m_fck" },
+};
+
static struct omap_hwmod omap2430_dss_venc_hwmod = {
.name = "dss_venc",
.class = &omap2430_venc_hwmod_class,
@@ -1505,6 +1522,8 @@ static struct omap_hwmod omap2430_dss_venc_hwmod = {
.module_offs = CORE_MOD,
},
},
+ .opt_clks = venc_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks),
.slaves = omap2430_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dss_venc_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 909a84d..b327776 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"
@@ -84,6 +85,10 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod;
static struct omap_hwmod omap3xxx_mcbsp5_hwmod;
static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod;
static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod;
+static struct omap_hwmod omap34xx_usb_host_hs_hwmod;
+static struct omap_hwmod omap34xx_usbhs_ohci_hwmod;
+static struct omap_hwmod omap34xx_usbhs_ehci_hwmod;
+static struct omap_hwmod omap34xx_usb_tll_hs_hwmod;
/* L3 -> L4_CORE interface */
static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -396,6 +401,15 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+
+static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
+ {.name = "sr1_irq", .irq = 18},
+};
+
+static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
+ {.name = "sr2_irq", .irq = 19},
+};
+
/* L4 CORE -> SR1 interface */
static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
{
@@ -1542,9 +1556,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
};
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
- { .role = "tv_clk", .clk = "dss_tv_fck" },
- { .role = "video_clk", .clk = "dss_96m_fck" },
+ { .role = "dss_clk", .clk = "dss1_alwon_fck" },
+ /*
+ * The rest of the clocks are not needed by the driver,
+ * but are needed by the hwmod to reset DSS properly.
+ */
{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+ { .role = "tv_clk", .clk = "dss_tv_fck" },
+ /* required only on OMAP3430 */
+ { .role = "tv_dac_clk", .clk = "dss_96m_fck" },
};
static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1656,6 +1676,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
&omap3xxx_l4_core__dss_dispc,
};
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss1_alwon_fck" },
+};
+
static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap3xxx_dispc_hwmod_class,
@@ -1669,6 +1693,8 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.module_offs = OMAP3430_DSS_MOD,
},
},
+ .opt_clks = dispc_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks),
.slaves = omap3xxx_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1720,6 +1746,11 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
&omap3xxx_l4_core__dss_dsi1,
};
+static struct omap_hwmod_opt_clk dsi1_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss1_alwon_fck" },
+ { .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
.name = "dss_dsi1",
.class = &omap3xxx_dsi_hwmod_class,
@@ -1733,6 +1764,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
.module_offs = OMAP3430_DSS_MOD,
},
},
+ .opt_clks = dsi1_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(dsi1_opt_clks),
.slaves = omap3xxx_dss_dsi1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1791,6 +1824,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
&omap3xxx_l4_core__dss_rfbi,
};
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+ { .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
.name = "dss_rfbi",
.class = &omap3xxx_rfbi_hwmod_class,
@@ -1802,6 +1839,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
.module_offs = OMAP3430_DSS_MOD,
},
},
+ .opt_clks = rfbi_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks),
.slaves = omap3xxx_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1851,6 +1890,12 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
&omap3xxx_l4_core__dss_venc,
};
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+ { .role = "tv_clk", .clk = "dss_tv_fck" },
+ /* required only on OMAP3430 */
+ { .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
.name = "dss_venc",
.class = &omap3xxx_venc_hwmod_class,
@@ -1862,6 +1907,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
.module_offs = OMAP3430_DSS_MOD,
},
},
+ .opt_clks = venc_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks),
.slaves = omap3xxx_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_venc_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -2910,6 +2957,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,
};
@@ -2918,7 +2969,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,
@@ -2930,9 +2980,12 @@ 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),
+ .mpu_irqs = omap3_smartreflex_mpu_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs),
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
@@ -2940,7 +2993,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,
@@ -2952,10 +3004,17 @@ 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),
+ .mpu_irqs = omap3_smartreflex_mpu_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs),
};
/* 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,
};
@@ -2964,7 +3023,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,
@@ -2976,9 +3034,12 @@ 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),
+ .mpu_irqs = omap3_smartreflex_core_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs),
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
@@ -2986,7 +3047,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,
@@ -2998,7 +3058,10 @@ 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),
+ .mpu_irqs = omap3_smartreflex_core_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs),
};
/*
@@ -3574,6 +3637,276 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
+/*
+ * 'usb_host_hs' class
+ * high-speed multi-port usb host controller
+ */
+static struct omap_hwmod_ocp_if omap34xx_usb_host_hs__l3_main_2 = {
+ .master = &omap34xx_usb_host_hs_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_class_sysconfig omap34xx_usb_host_hs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .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_type1,
+};
+
+static struct omap_hwmod_class omap34xx_usb_host_hs_hwmod_class = {
+ .name = "usbhs_uhh",
+ .sysc = &omap34xx_usb_host_hs_sysc,
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_masters[] = {
+ &omap34xx_usb_host_hs__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap34xx_usb_host_hs_addrs[] = {
+ {
+ .name = "uhh",
+ .pa_start = 0x48064000,
+ .pa_end = 0x480643ff,
+ .flags = ADDR_TYPE_RT
+ }
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_host_hs = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_usb_host_hs_hwmod,
+ .clk = "l4_ick",
+ .addr = omap34xx_usb_host_hs_addrs,
+ .addr_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if omap34xx_f128m_cfg__usb_host_hs = {
+ .clk = "usbhost_120m_fck",
+ .user = OCP_USER_MPU,
+ .flags = OCPIF_SWSUP_IDLE,
+};
+
+static struct omap_hwmod_ocp_if omap34xx_f48m_cfg__usb_host_hs = {
+ .clk = "usbhost_48m_fck",
+ .user = OCP_USER_MPU,
+ .flags = OCPIF_SWSUP_IDLE,
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_slaves[] = {
+ &omap34xx_l4_cfg__usb_host_hs,
+ &omap34xx_f128m_cfg__usb_host_hs,
+ &omap34xx_f48m_cfg__usb_host_hs,
+};
+
+static struct omap_hwmod omap34xx_usb_host_hs_hwmod = {
+ .name = "usbhs_uhh",
+ .class = &omap34xx_usb_host_hs_hwmod_class,
+ .main_clk = "usbhost_ick",
+ .prcm = {
+ .omap2 = {
+ .module_offs = OMAP3430ES2_USBHOST_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = 0,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = 1,
+ .idlest_stdby_bit = 0,
+ },
+ },
+ .slaves = omap34xx_usb_host_hs_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_slaves),
+ .masters = omap34xx_usb_host_hs_masters,
+ .masters_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_masters),
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* 'usbhs_ohci' class */
+static struct omap_hwmod_ocp_if omap34xx_usbhs_ohci__l3_main_2 = {
+ .master = &omap34xx_usbhs_ohci_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_class omap34xx_usbhs_ohci_hwmod_class = {
+ .name = "usbhs_ohci",
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usbhs_ohci_masters[] = {
+ &omap34xx_usbhs_ohci__l3_main_2,
+};
+
+static struct omap_hwmod_irq_info omap34xx_usbhs_ohci_irqs[] = {
+ { .name = "ohci-irq", .irq = 76 },
+};
+
+static struct omap_hwmod_addr_space omap34xx_usbhs_ohci_addrs[] = {
+ {
+ .name = "ohci",
+ .pa_start = 0x48064400,
+ .pa_end = 0x480647FF,
+ .flags = ADDR_MAP_ON_INIT
+ }
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usbhs_ohci = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_usbhs_ohci_hwmod,
+ .clk = "l4_ick",
+ .addr = omap34xx_usbhs_ohci_addrs,
+ .addr_cnt = ARRAY_SIZE(omap34xx_usbhs_ohci_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usbhs_ohci_slaves[] = {
+ &omap34xx_l4_cfg__usbhs_ohci,
+};
+
+static struct omap_hwmod omap34xx_usbhs_ohci_hwmod = {
+ .name = "usbhs_ohci",
+ .class = &omap34xx_usbhs_ohci_hwmod_class,
+ .mpu_irqs = omap34xx_usbhs_ohci_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usbhs_ohci_irqs),
+ .slaves = omap34xx_usbhs_ohci_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usbhs_ohci_slaves),
+ .masters = omap34xx_usbhs_ohci_masters,
+ .masters_cnt = ARRAY_SIZE(omap34xx_usbhs_ohci_masters),
+ .flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* 'usbhs_ehci' class */
+static struct omap_hwmod_ocp_if omap34xx_usbhs_ehci__l3_main_2 = {
+ .master = &omap34xx_usbhs_ehci_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_class omap34xx_usbhs_ehci_hwmod_class = {
+ .name = "usbhs_ehci",
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usbhs_ehci_masters[] = {
+ &omap34xx_usbhs_ehci__l3_main_2,
+};
+
+static struct omap_hwmod_irq_info omap34xx_usbhs_ehci_irqs[] = {
+ { .name = "ehci-irq", .irq = 77 },
+};
+
+static struct omap_hwmod_addr_space omap34xx_usbhs_ehci_addrs[] = {
+ {
+ .name = "ehci",
+ .pa_start = 0x48064800,
+ .pa_end = 0x48064CFF,
+ .flags = ADDR_MAP_ON_INIT
+ }
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usbhs_ehci = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_usbhs_ehci_hwmod,
+ .clk = "l4_ick",
+ .addr = omap34xx_usbhs_ehci_addrs,
+ .addr_cnt = ARRAY_SIZE(omap34xx_usbhs_ehci_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usbhs_ehci_slaves[] = {
+ &omap34xx_l4_cfg__usbhs_ehci,
+};
+
+static struct omap_hwmod omap34xx_usbhs_ehci_hwmod = {
+ .name = "usbhs_ehci",
+ .class = &omap34xx_usbhs_ehci_hwmod_class,
+ .mpu_irqs = omap34xx_usbhs_ehci_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usbhs_ehci_irqs),
+ .slaves = omap34xx_usbhs_ehci_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usbhs_ehci_slaves),
+ .masters = omap34xx_usbhs_ehci_masters,
+ .masters_cnt = ARRAY_SIZE(omap34xx_usbhs_ehci_masters),
+ .flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/*
+ * 'usb_tll_hs' class
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
+ */
+static struct omap_hwmod_class_sysconfig omap34xx_usb_tll_hs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap34xx_usb_tll_hs_hwmod_class = {
+ .name = "usbhs_tll",
+ .sysc = &omap34xx_usb_tll_hs_sysc,
+};
+
+static struct omap_hwmod_irq_info omap34xx_usb_tll_hs_irqs[] = {
+ { .name = "tll-irq", .irq = 78 },
+};
+
+static struct omap_hwmod_addr_space omap34xx_usb_tll_hs_addrs[] = {
+ {
+ .name = "tll",
+ .pa_start = 0x48062000,
+ .pa_end = 0x48062fff,
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+static struct omap_hwmod_ocp_if omap34xx_f_cfg__usb_tll_hs = {
+ .clk = "usbtll_fck",
+ .user = OCP_USER_MPU,
+ .flags = OCPIF_SWSUP_IDLE,
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_tll_hs = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_usb_tll_hs_hwmod,
+ .clk = "l4_ick",
+ .addr = omap34xx_usb_tll_hs_addrs,
+ .addr_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_usb_tll_hs_slaves[] = {
+ &omap34xx_l4_cfg__usb_tll_hs,
+ &omap34xx_f_cfg__usb_tll_hs,
+};
+
+static struct omap_hwmod omap34xx_usb_tll_hs_hwmod = {
+ .name = "usbhs_tll",
+ .class = &omap34xx_usb_tll_hs_hwmod_class,
+ .mpu_irqs = omap34xx_usb_tll_hs_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_irqs),
+ .main_clk = "usbtll_ick",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 3,
+ .module_bit = 2,
+ .idlest_reg_id = 3,
+ .idlest_idle_bit = 2,
+ },
+ },
+ .slaves = omap34xx_usb_tll_hs_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_slaves),
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_l3_main_hwmod,
&omap3xxx_l4_core_hwmod,
@@ -3656,6 +3989,11 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
/* usbotg for am35x */
&am35xx_usbhsotg_hwmod,
+ &omap34xx_usb_host_hs_hwmod,
+ &omap34xx_usbhs_ohci_hwmod,
+ &omap34xx_usbhs_ehci_hwmod,
+ &omap34xx_usb_tll_hs_hwmod,
+
NULL,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e1c69ff..b5c5b10 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -27,9 +27,11 @@
#include <plat/mcspi.h>
#include <plat/mcbsp.h>
#include <plat/mmc.h>
+#include <plat/dmtimer.h>
#include "omap_hwmod_common_data.h"
+#include "smartreflex.h"
#include "cm1_44xx.h"
#include "cm2_44xx.h"
#include "prm44xx.h"
@@ -49,6 +51,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,7 +69,12 @@ 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;
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod;
+static struct omap_hwmod omap44xx_usbhs_ohci_hwmod;
+static struct omap_hwmod omap44xx_usbhs_ehci_hwmod;
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod;
/*
* Interconnects omap_hwmod structures
@@ -124,7 +133,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 +182,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 +221,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 +315,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 +327,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 +359,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 +415,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 +428,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 +478,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 +535,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 +557,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 +579,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 +601,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 +631,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 +656,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
* elm
* emif1
* emif2
- * fdif
* gpmc
* gpu
* hdq1w
@@ -640,7 +666,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
* prcm_mpu
* prm
* scrm
- * sl2if
* slimbus1
* slimbus2
* usb_host_fs
@@ -651,6 +676,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 +899,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 +933,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 +972,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
@@ -743,13 +1026,132 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+ .context_reg = OMAP4430_RM_ABE_AESS_CONTEXT,
},
},
.slaves = omap44xx_aess_slaves,
.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),
+};
+
+/*
+ * 'ctrl_module' class
+ * attila core control module
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_ctrl_module_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_ctrl_module_hwmod_class = {
+ .name = "ctrl_module",
+ .sysc = &omap44xx_ctrl_module_sysc,
+};
+
+/* ctrl_module_core */
+static struct omap_hwmod omap44xx_ctrl_module_core_hwmod;
+static struct omap_hwmod_irq_info omap44xx_ctrl_module_core_irqs[] = {
+ { .name = "sec_evts", .irq = 8 + OMAP44XX_IRQ_GIC_START },
+ { .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_ctrl_module_core_addrs[] = {
+ {
+ .pa_start = 0x4a002000,
+ .pa_end = 0x4a0027ff,
+
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+/* l4_cfg -> ctrl_module_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ctrl_module_core = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_ctrl_module_core_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_ctrl_module_core_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_ctrl_module_core_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ctrl_module_core slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_ctrl_module_core_slaves[] = {
+ &omap44xx_l4_cfg__ctrl_module_core,
+};
+
+static struct omap_hwmod omap44xx_ctrl_module_core_hwmod = {
+ .name = "ctrl_module_core",
+ .class = &omap44xx_ctrl_module_hwmod_class,
+ .mpu_irqs = omap44xx_ctrl_module_core_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_ctrl_module_core_irqs),
+ .main_clk = "l4_div_ck",
+ .slaves = omap44xx_ctrl_module_core_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_ctrl_module_core_slaves),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X),
+};
+/*
+ * 'thermal_sensor' class
+ * thermal sensor module inside the bandgap / control module
+ */
+
+static struct omap_hwmod_class omap44xx_thermal_sensor_hwmod_class = {
+ .name = "thermal_sensor",
+};
+
+static struct omap_hwmod_irq_info omap44xx_thermal_sensor_irqs[] = {
+ { .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_thermal_sensor_addrs[] = {
+ {
+ .pa_start = 0x4a002378,
+ .pa_end = 0x4a0023ff,
+ },
+};
+
+static struct omap_hwmod omap44xx_thermal_sensor_hwmod;
+/* l4_cfg -> ctrl_module_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__thermal_sensor = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_thermal_sensor_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_thermal_sensor_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_thermal_sensor_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ctrl_module_core slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_thermal_sensor_slaves[] = {
+ &omap44xx_l4_cfg__thermal_sensor,
+};
+
+static struct omap_hwmod_opt_clk thermal_sensor446x_opt_clks[] = {
+ { .role = "fclk", .clk = "bandgap_ts_fclk" },
+};
+
+static struct omap_hwmod omap44xx_thermal_sensor_hwmod = {
+ .name = "thermal_sensor",
+ .class = &omap44xx_thermal_sensor_hwmod_class,
+ .mpu_irqs = omap44xx_thermal_sensor_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_thermal_sensor_irqs),
+ .main_clk = "bandgap_ts_fclk",
+ .slaves = omap44xx_thermal_sensor_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_thermal_sensor_slaves),
+ .prcm = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ },
+ },
+ .opt_clks = thermal_sensor446x_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(thermal_sensor446x_opt_clks),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X),
};
/*
@@ -762,11 +1164,28 @@ 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 = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ },
+ },
+ .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 = {
@@ -774,9 +1193,9 @@ 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 = bandgap446x_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(bandgap446x_opt_clks),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X),
};
/*
@@ -835,7 +1254,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 +1340,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 +1430,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 +1455,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 +1470,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 +1490,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 +1512,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 +1534,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),
};
/*
@@ -1110,9 +1548,67 @@ static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = {
.sysc_flags = SYSS_HAS_RESET_STATUS,
};
+static int omap44xx_dss_reset(struct omap_hwmod *oh)
+{
+#define DISPC_IRQSTATUS (0x48041018UL)
+#define DISPC_CONTROL1 (0x48041040UL)
+#define DISPC_CONTROL2 (0x48041238UL)
+ u32 ctrl1_mask = 0;
+ u32 ctrl2_mask = 0;
+ u32 irq_mask = 0;
+ u32 val;
+ unsigned long end_wait;
+
+ /* HACK */
+ /* If LCD1/LCD2/TV are active, disable them first before
+ * moving the clock sources back to PRCM. We don't want to change
+ * the clock source while a DMA is active.
+ */
+ val = omap_readl(DISPC_CONTROL1);
+ if (val & (1 << 0)) {
+ /* LCD1 */
+ irq_mask |= 1 << 0;
+ ctrl1_mask |= 1 << 0;
+ }
+ if (val & (1 << 1)) {
+ /* TV/VENC */
+ irq_mask |= 1 << 24;
+ ctrl1_mask |= 1 << 1;
+ }
+ val = omap_readl(DISPC_CONTROL2);
+ if (val & (1 << 0)) {
+ /* LCD2 */
+ irq_mask |= 1 << 22;
+ ctrl2_mask |= 1 << 0;
+ }
+
+ /* disable the active controllers */
+ omap_writel(omap_readl(DISPC_CONTROL1) & (~ctrl1_mask), DISPC_CONTROL1);
+ omap_writel(omap_readl(DISPC_CONTROL2) & (~ctrl2_mask), DISPC_CONTROL2);
+
+ omap_writel(irq_mask, DISPC_IRQSTATUS);
+
+ end_wait = jiffies + msecs_to_jiffies(50);
+ while (((omap_readl(DISPC_CONTROL1) & ctrl1_mask) ||
+ (omap_readl(DISPC_CONTROL2) & ctrl2_mask) ||
+ ((omap_readl(DISPC_IRQSTATUS) & irq_mask) != irq_mask)) &&
+ time_before(jiffies, end_wait))
+ cpu_relax();
+ WARN_ON((omap_readl(DISPC_CONTROL1) & ctrl1_mask) ||
+ (omap_readl(DISPC_CONTROL2) & ctrl2_mask) ||
+ ((omap_readl(DISPC_IRQSTATUS) & irq_mask) != irq_mask));
+
+ omap_hwmod_write(0x0, oh, 0x40);
+ return 0;
+#undef DISPC_IRQSTATUS
+#undef DISPC_CONTROL1
+#undef DISPC_CONTROL2
+}
+
static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
.name = "dss",
.sysc = &omap44xx_dss_sysc,
+ .reset = omap44xx_dss_reset,
};
/* dss */
@@ -1164,15 +1660,15 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
};
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
- { .role = "sys_clk", .clk = "dss_sys_clk" },
- { .role = "tv_clk", .clk = "dss_tv_clk" },
{ .role = "dss_clk", .clk = "dss_dss_clk" },
- { .role = "video_clk", .clk = "dss_48mhz_clk" },
};
static struct omap_hwmod omap44xx_dss_hwmod = {
.name = "dss_core",
.class = &omap44xx_dss_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_INIT_NO_RESET,
+#endif
.main_clk = "dss_fck",
.prcm = {
.omap4 = {
@@ -1185,7 +1681,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),
};
/*
@@ -1263,9 +1759,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
&omap44xx_l4_per__dss_dispc,
};
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss_dss_clk" },
+ /*
+ * The rest of the clocks are not needed by the driver,
+ * but are needed by the hwmod to reset DSS properly.
+ */
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+ { .role = "tv_clk", .clk = "dss_tv_clk" },
+ { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap44xx_dispc_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET | HWMOD_INIT_NO_RESET,
+#else
+ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+#endif
.mpu_irqs = omap44xx_dss_dispc_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_irqs),
.sdma_reqs = omap44xx_dss_dispc_sdma_reqs,
@@ -1274,11 +1786,14 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .context_reg = OMAP4430_RM_DSS_DSS_CONTEXT,
},
},
+ .opt_clks = dispc_opt_clks,
+ .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),
};
/*
@@ -1354,9 +1869,17 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
&omap44xx_l4_per__dss_dsi1,
};
+static struct omap_hwmod_opt_clk dsi1_opt_clks[] = {
+ { .role = "dss_clk", .clk = "dss_dss_clk" },
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
.name = "dss_dsi1",
.class = &omap44xx_dsi_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_INIT_NO_RESET,
+#endif
.mpu_irqs = omap44xx_dss_dsi1_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
.sdma_reqs = omap44xx_dss_dsi1_sdma_reqs,
@@ -1367,9 +1890,11 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
},
},
+ .opt_clks = dsi1_opt_clks,
+ .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 */
@@ -1427,6 +1952,9 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
.name = "dss_dsi2",
.class = &omap44xx_dsi_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_INIT_NO_RESET,
+#endif
.mpu_irqs = omap44xx_dss_dsi2_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
.sdma_reqs = omap44xx_dss_dsi2_sdma_reqs,
@@ -1439,7 +1967,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),
};
/*
@@ -1514,9 +2042,17 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
&omap44xx_l4_per__dss_hdmi,
};
+static struct omap_hwmod_opt_clk hdmi_opt_clks[] = {
+ { .role = "sys_clk", .clk = "dss_sys_clk" },
+ { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
.name = "dss_hdmi",
.class = &omap44xx_hdmi_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_INIT_NO_RESET,
+#endif
.mpu_irqs = omap44xx_dss_hdmi_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
.sdma_reqs = omap44xx_dss_hdmi_sdma_reqs,
@@ -1527,9 +2063,11 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
},
},
+ .opt_clks = hdmi_opt_clks,
+ .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),
};
/*
@@ -1600,9 +2138,16 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
&omap44xx_l4_per__dss_rfbi,
};
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+ { .role = "rfbi_iclk", .clk = "dss_fck" },
+};
+
static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
.name = "dss_rfbi",
.class = &omap44xx_rfbi_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_INIT_NO_RESET,
+#endif
.sdma_reqs = omap44xx_dss_rfbi_sdma_reqs,
.sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
.main_clk = "dss_fck",
@@ -1611,9 +2156,11 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
},
},
+ .opt_clks = rfbi_opt_clks,
+ .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),
};
/*
@@ -1669,18 +2216,209 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
&omap44xx_l4_per__dss_venc,
};
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+ { .role = "tv_clk", .clk = "dss_tv_clk" },
+};
+
static struct omap_hwmod omap44xx_dss_venc_hwmod = {
.name = "dss_venc",
.class = &omap44xx_venc_hwmod_class,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .flags = HWMOD_INIT_NO_RESET,
+#endif
.main_clk = "dss_fck",
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
},
},
+ .opt_clks = venc_opt_clks,
+ .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),
+};
+
+/*
+ * 'emif' class
+ * external memory interface no1
+ */
+
+static struct omap_hwmod_class omap44xx_emif_hwmod_class = {
+ .name = "emif",
+};
+
+/* emif1 */
+static struct omap_hwmod omap44xx_emif1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_emif1_irqs[] = {
+ { .irq = 110 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_emif1_addrs[] = {
+ {
+ .pa_start = 0x4c000000,
+ .pa_end = 0x4c0000ff,
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+/* emif_fw -> emif1 */
+static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif1 = {
+ .master = &omap44xx_emif_fw_hwmod,
+ .slave = &omap44xx_emif1_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_emif1_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_emif1_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* emif1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_emif1_slaves[] = {
+ &omap44xx_emif_fw__emif1,
+};
+
+static struct omap_hwmod omap44xx_emif1_hwmod = {
+ .name = "emif1",
+ .class = &omap44xx_emif_hwmod_class,
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+ .mpu_irqs = omap44xx_emif1_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_emif1_irqs),
+ .main_clk = "emif1_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
+ },
+ },
+ .slaves = omap44xx_emif1_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_emif1_slaves),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+};
+
+/* emif2 */
+static struct omap_hwmod omap44xx_emif2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_emif2_irqs[] = {
+ { .irq = 111 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_emif2_addrs[] = {
+ {
+ .pa_start = 0x4d000000,
+ .pa_end = 0x4d0000ff,
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+/* emif_fw -> emif2 */
+static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif2 = {
+ .master = &omap44xx_emif_fw_hwmod,
+ .slave = &omap44xx_emif2_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_emif2_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_emif2_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* emif2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_emif2_slaves[] = {
+ &omap44xx_emif_fw__emif2,
+};
+
+static struct omap_hwmod omap44xx_emif2_hwmod = {
+ .name = "emif2",
+ .class = &omap44xx_emif_hwmod_class,
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+ .mpu_irqs = omap44xx_emif2_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_emif2_irqs),
+ .main_clk = "emif2_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
+ },
+ },
+ .slaves = omap44xx_emif2_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_emif2_slaves),
+ .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,
+ /*
+ * FDIF needs 100 OCP clk cycles delay after a softreset before
+ * accessing sysconfig again.
+ * The lowest frequency at the moment for L3 bus is 100 MHz, so
+ * 1usec delay is needed. Add an x2 margin to be safe (2 usecs).
+ *
+ * TODO: Indicate errata when available.
+ */
+ .srst_udelay = 2,
+ .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),
};
/*
@@ -1745,15 +2483,37 @@ 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,
+ .context_reg = OMAP4430_RM_WKUP_GPIO1_CONTEXT,
+ },
+ },
+ .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",
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+ .context_reg = OMAP4430_RM_WKUP_GPIO1_CONTEXT,
},
},
.opt_clks = gpio1_opt_clks,
@@ -1761,7 +2521,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 */
@@ -1807,6 +2567,7 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_GPIO2_CONTEXT,
},
},
.opt_clks = gpio2_opt_clks,
@@ -1814,7 +2575,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 */
@@ -1860,6 +2621,7 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_GPIO3_CONTEXT,
},
},
.opt_clks = gpio3_opt_clks,
@@ -1867,7 +2629,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 */
@@ -1913,6 +2675,7 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_GPIO4_CONTEXT,
},
},
.opt_clks = gpio4_opt_clks,
@@ -1920,7 +2683,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 */
@@ -1966,6 +2729,7 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_GPIO5_CONTEXT,
},
},
.opt_clks = gpio5_opt_clks,
@@ -1973,7 +2737,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 */
@@ -2019,6 +2783,7 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_GPIO6_CONTEXT,
},
},
.opt_clks = gpio6_opt_clks,
@@ -2026,7 +2791,45 @@ 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 |
+ SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+ .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
+ },
};
/*
@@ -2044,7 +2847,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_hsi_sysc = {
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
- MSTANDBY_SMART),
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type1,
};
@@ -2103,7 +2906,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),
};
/*
@@ -2177,7 +3014,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 */
@@ -2230,7 +3067,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 */
@@ -2283,7 +3120,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 */
@@ -2336,7 +3173,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),
};
/*
@@ -2365,6 +3202,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,
@@ -2375,6 +3220,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,
};
@@ -2395,7 +3242,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 */
@@ -2410,12 +3257,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,
@@ -2431,7 +3279,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),
};
/*
@@ -2442,6 +3290,15 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
.rev_offs = 0x0000,
.sysc_offs = 0x0010,
+ /*
+ * ISS needs 100 OCP clk cycles delay after a softreset before
+ * accessing sysconfig again.
+ * The lowest frequency at the moment for L3 bus is 100 MHz, so
+ * 1usec delay is needed. Add an x2 margin to be safe (2 usecs).
+ *
+ * TODO: Indicate errata when available.
+ */
+ .srst_udelay = 2,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -2518,7 +3375,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),
};
/*
@@ -2549,8 +3406,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,
};
@@ -2591,7 +3456,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 */
@@ -2606,7 +3471,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 = {
@@ -2627,7 +3492,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),
};
/*
@@ -2694,7 +3598,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),
};
/*
@@ -2758,7 +3662,105 @@ 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),
+};
+
+/*
+ * 'mcasp' class
+ * multi channel audio serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcasp_sysc = {
+ .sysc_offs = 0x0004,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class omap44xx_mcasp_hwmod_class = {
+ .name = "omap-mcasp-dai",
+ .sysc = &omap44xx_mcasp_sysc,
+};
+
+/* mcasp */
+static struct omap_hwmod omap44xx_mcasp_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcasp_irqs[] = {
+ { .irq = 109 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcasp_sdma_reqs[] = {
+ { .name = "tx", .dma_req = 7 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcasp_addrs[] = {
+ {
+ .pa_start = 0x40128000,
+ .pa_end = 0x40128000 + SZ_4K - 1, /* McASP CFG Port */
+ .flags = ADDR_TYPE_RT
+ },
+ {
+ .pa_start = 0x4012A000,
+ .pa_end = 0x4012A000 + SZ_4K - 1, /* McASP Data Port */
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+/* l4_abe -> mcasp */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcasp = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcasp_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcasp_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_mcasp_addrs),
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcasp_dma_addrs[] = {
+ {
+ .pa_start = 0x49028000,
+ .pa_end = 0x49028000 + SZ_4K - 1, /* McASP CFG Port */
+ .flags = ADDR_TYPE_RT
+ },
+ {
+ .pa_start = 0x4902A000,
+ .pa_end = 0x4902A000 + SZ_4K - 1, /* McASP Data Port */
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+/* l4_abe -> mcasp (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcasp_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcasp_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcasp_dma_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_mcasp_dma_addrs),
+ .user = OCP_USER_SDMA,
+};
+
+/* mcasp1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcasp_slaves[] = {
+ &omap44xx_l4_abe__mcasp,
+ &omap44xx_l4_abe__mcasp_dma,
+};
+
+static struct omap_hwmod omap44xx_mcasp_hwmod = {
+ .name = "omap-mcasp-dai",
+ .class = &omap44xx_mcasp_hwmod_class,
+ .flags = HWMOD_SWSUP_SIDLE,
+ .mpu_irqs = omap44xx_mcasp_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcasp_irqs),
+ .sdma_reqs = omap44xx_mcasp_sdma_reqs,
+ .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcasp_sdma_reqs),
+ .main_clk = "mcasp_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ },
+ },
+ .slaves = omap44xx_mcasp_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_mcasp_slaves),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
};
/*
@@ -2783,7 +3785,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[] = {
@@ -2850,13 +3853,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[] = {
@@ -2923,13 +3927,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[] = {
@@ -2996,13 +4001,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[] = {
@@ -3048,7 +4054,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),
};
/*
@@ -3136,11 +4142,12 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+ .context_reg = OMAP4430_RM_ABE_PDM_CONTEXT,
},
},
.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),
};
/*
@@ -3226,7 +4233,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 */
@@ -3286,7 +4293,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 */
@@ -3346,7 +4353,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 */
@@ -3404,7 +4411,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),
};
/*
@@ -3419,7 +4426,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_mmc_sysc = {
SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
SYSC_HAS_SOFTRESET),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+ MSTANDBY_FORCE | MSTANDBY_NO |
MSTANDBY_SMART),
.sysc_fields = &omap_hwmod_sysc_type2,
};
@@ -3484,6 +4491,7 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+ .context_reg = OMAP4430_RM_L3INIT_MMC1_CONTEXT,
},
},
.dev_attr = &mmc1_dev_attr,
@@ -3491,7 +4499,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 */
@@ -3543,13 +4551,14 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+ .context_reg = OMAP4430_RM_L3INIT_MMC2_CONTEXT,
},
},
.slaves = omap44xx_mmc2_slaves,
.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 */
@@ -3597,11 +4606,12 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_MMCSD3_CONTEXT,
},
},
.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 */
@@ -3649,11 +4659,12 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_MMCSD4_CONTEXT,
},
},
.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 */
@@ -3701,215 +4712,12 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_MMCSD5_CONTEXT,
},
},
.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),
};
/*
@@ -3970,7 +4778,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),
};
/*
@@ -3994,6 +4802,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
static struct omap_hwmod_class omap44xx_timer_1ms_hwmod_class = {
.name = "timer",
.sysc = &omap44xx_timer_1ms_sysc,
+ .rev = OMAP_TIMER_IP_VERSION_1,
};
static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
@@ -4009,6 +4818,12 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
.name = "timer",
.sysc = &omap44xx_timer_sysc,
+ .rev = OMAP_TIMER_IP_VERSION_2,
+};
+
+/* secure timer can assign this to .dev_attr field */
+static struct omap_secure_timer_dev_attr secure_timer_dev_attr = {
+ .is_secure_timer = true,
};
/* timer1 */
@@ -4053,7 +4868,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 */
@@ -4094,11 +4909,12 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_DMTIMER2_CONTEXT,
},
},
.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 */
@@ -4139,11 +4955,12 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_DMTIMER3_CONTEXT,
},
},
.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 */
@@ -4184,11 +5001,12 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_DMTIMER4_CONTEXT,
},
},
.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 */
@@ -4248,11 +5066,12 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+ .context_reg = OMAP4430_RM_ABE_TIMER5_CONTEXT,
},
},
.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 */
@@ -4312,11 +5131,12 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+ .context_reg = OMAP4430_RM_ABE_TIMER6_CONTEXT,
},
},
.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 */
@@ -4376,11 +5196,12 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+ .context_reg = OMAP4430_RM_ABE_TIMER7_CONTEXT,
},
},
.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 */
@@ -4440,11 +5261,12 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+ .context_reg = OMAP4430_RM_ABE_TIMER8_CONTEXT,
},
},
.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 */
@@ -4485,11 +5307,12 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_DMTIMER9_CONTEXT,
},
},
.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 */
@@ -4530,11 +5353,12 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_DMTIMER10_CONTEXT,
},
},
.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 */
@@ -4575,11 +5399,12 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_DMTIMER11_CONTEXT,
},
},
.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),
};
/*
@@ -4641,6 +5466,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
static struct omap_hwmod omap44xx_uart1_hwmod = {
.name = "uart1",
.class = &omap44xx_uart_hwmod_class,
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = omap44xx_uart1_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart1_irqs),
.sdma_reqs = omap44xx_uart1_sdma_reqs,
@@ -4649,11 +5475,12 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_UART1_CONTEXT,
},
},
.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 */
@@ -4701,11 +5528,12 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_UART2_CONTEXT,
},
},
.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 */
@@ -4754,11 +5582,12 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_UART3_CONTEXT,
},
},
.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 */
@@ -4806,11 +5635,12 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
.prcm = {
.omap4 = {
.clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+ .context_reg = OMAP4430_RM_L4PER_UART4_CONTEXT,
},
},
.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),
};
/*
@@ -4892,7 +5722,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),
};
/*
@@ -4960,7 +5790,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 */
@@ -5024,7 +5854,235 @@ 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),
+};
+
+/*
+ * 'usb_host_hs' class
+ * high-speed multi-port usb host controller
+ */
+static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = {
+ .master = &omap44xx_usb_host_hs_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART |
+ MSTANDBY_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = {
+ .name = "usbhs_uhh",
+ .sysc = &omap44xx_usb_host_hs_sysc,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = {
+ &omap44xx_usb_host_hs__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = {
+ {
+ .name = "uhh",
+ .pa_start = 0x4a064000,
+ .pa_end = 0x4a0647ff,
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_usb_host_hs_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_usb_host_hs_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = {
+ &omap44xx_l4_cfg__usb_host_hs,
+};
+
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
+ .name = "usbhs_uhh",
+ .class = &omap44xx_usb_host_hs_hwmod_class,
+ .main_clk = "usb_host_hs_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ },
+ },
+ .slaves = omap44xx_usb_host_hs_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves),
+ .masters = omap44xx_usb_host_hs_masters,
+ .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters),
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+};
+
+/* 'usbhs_ohci' class */
+static struct omap_hwmod_class omap44xx_usbhs_ohci_hwmod_class = {
+ .name = "usbhs_ohci",
+};
+
+static struct omap_hwmod_irq_info omap44xx_usbhs_ohci_irqs[] = {
+ { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_usbhs_ohci_addrs[] = {
+ {
+ .name = "ohci",
+ .pa_start = 0x4A064800,
+ .pa_end = 0x4A064BFF,
+ .flags = ADDR_MAP_ON_INIT
+ }
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usbhs_ohci = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_usbhs_ohci_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_usbhs_ohci_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_usbhs_ohci_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usbhs_ohci_slaves[] = {
+ &omap44xx_l4_cfg__usbhs_ohci,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usbhs_ohci_masters[] = {
+ &omap44xx_usb_host_hs__l3_main_2,
+};
+
+static struct omap_hwmod omap44xx_usbhs_ohci_hwmod = {
+ .name = "usbhs_ohci",
+ .class = &omap44xx_usbhs_ohci_hwmod_class,
+ .mpu_irqs = omap44xx_usbhs_ohci_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usbhs_ohci_irqs),
+ .slaves = omap44xx_usbhs_ohci_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usbhs_ohci_slaves),
+ .masters = omap44xx_usbhs_ohci_masters,
+ .masters_cnt = ARRAY_SIZE(omap44xx_usbhs_ohci_masters),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+ .flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
+};
+
+/* 'usbhs_ehci' class */
+static struct omap_hwmod_class omap44xx_usbhs_ehci_hwmod_class = {
+ .name = "usbhs_ehci",
+};
+
+static struct omap_hwmod_irq_info omap44xx_usbhs_ehci_irqs[] = {
+ { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_usbhs_ehci_addrs[] = {
+ {
+ .name = "ehci",
+ .pa_start = 0x4A064C00,
+ .pa_end = 0x4A064FFF,
+ .flags = ADDR_MAP_ON_INIT
+ }
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usbhs_ehci = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_usbhs_ehci_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_usbhs_ehci_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_usbhs_ehci_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usbhs_ehci_slaves[] = {
+ &omap44xx_l4_cfg__usbhs_ehci,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usbhs_ehci_masters[] = {
+ &omap44xx_usb_host_hs__l3_main_2,
+};
+
+
+static struct omap_hwmod omap44xx_usbhs_ehci_hwmod = {
+ .name = "usbhs_ehci",
+ .class = &omap44xx_usbhs_ehci_hwmod_class,
+ .mpu_irqs = omap44xx_usbhs_ehci_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usbhs_ehci_irqs),
+ .slaves = omap44xx_usbhs_ehci_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usbhs_ehci_slaves),
+ .masters = omap44xx_usbhs_ehci_masters,
+ .masters_cnt = ARRAY_SIZE(omap44xx_usbhs_ehci_masters),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+ .flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'usb_tll_hs' class
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
+ */
+static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = {
+ .name = "usbhs_tll",
+ .sysc = &omap44xx_usb_tll_hs_sysc,
+};
+
+static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = {
+ { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = {
+ {
+ .name = "tll",
+ .pa_start = 0x4a062000,
+ .pa_end = 0x4a063fff,
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_usb_tll_hs_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_usb_tll_hs_addrs,
+ .addr_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = {
+ &omap44xx_l4_cfg__usb_tll_hs,
+};
+
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
+ .name = "usbhs_tll",
+ .class = &omap44xx_usb_tll_hs_hwmod_class,
+ .mpu_irqs = omap44xx_usb_tll_hs_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_irqs),
+ .main_clk = "usb_tll_hs_ick",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+ },
+ },
+ .slaves = omap44xx_usb_tll_hs_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves),
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
};
static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
@@ -5051,10 +6109,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, */
@@ -5078,8 +6137,13 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_dss_rfbi_hwmod,
&omap44xx_dss_venc_hwmod,
+ /* emif class */
+ &omap44xx_emif1_hwmod,
+ &omap44xx_emif2_hwmod,
+
/* gpio class */
- &omap44xx_gpio1_hwmod,
+ &omap443x_gpio1_hwmod,
+ &omap446x_gpio1_hwmod,
&omap44xx_gpio2_hwmod,
&omap44xx_gpio3_hwmod,
&omap44xx_gpio4_hwmod,
@@ -5087,7 +6151,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_gpio6_hwmod,
/* hsi class */
-/* &omap44xx_hsi_hwmod, */
+ &omap44xx_hsi_hwmod,
+
+ /* gpu class */
+ &omap44xx_gpu_hwmod,
/* i2c class */
&omap44xx_i2c1_hwmod,
@@ -5101,19 +6168,28 @@ 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,
/* mailbox class */
&omap44xx_mailbox_hwmod,
+ /* mcasp class */
+ &omap44xx_mcasp_hwmod,
+
/* mcbsp class */
&omap44xx_mcbsp1_hwmod,
&omap44xx_mcbsp2_hwmod,
@@ -5121,7 +6197,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_mcbsp4_hwmod,
/* mcpdm class */
-/* &omap44xx_mcpdm_hwmod, */
+ &omap44xx_mcpdm_hwmod,
/* mcspi class */
&omap44xx_mcspi1_hwmod,
@@ -5160,6 +6236,12 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_timer10_hwmod,
&omap44xx_timer11_hwmod,
+ /* ctrl module class */
+ &omap44xx_ctrl_module_core_hwmod,
+
+ /* thermal sensor hwmod */
+ &omap44xx_thermal_sensor_hwmod,
+
/* uart class */
&omap44xx_uart1_hwmod,
&omap44xx_uart2_hwmod,
@@ -5173,6 +6255,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_wd_timer2_hwmod,
&omap44xx_wd_timer3_hwmod,
+ &omap44xx_usb_host_hs_hwmod,
+ &omap44xx_usbhs_ohci_hwmod,
+ &omap44xx_usbhs_ehci_hwmod,
+ &omap44xx_usb_tll_hs_hwmod,
NULL,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c
index 08a1342..0312771 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c
@@ -49,6 +49,15 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
.srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT,
};
+/**
+ * struct omap_hwmod_sysc_type3 - TYPE3 sysconfig scheme.
+ *
+ * To be used by hwmod structure to specify the sysconfig offsets if the
+ * device ip is compliant only implements the sidle feature.
+ */
+struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3 = {
+ .sidle_shift = SYSC_TYPE3_SIDLEMODE_SHIFT,
+};
/*
* omap_hwmod class data
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
index 7b9f190..9d152de 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.c
+++ b/arch/arm/mach-omap2/omap_l3_noc.c
@@ -29,6 +29,29 @@
#include "omap_l3_noc.h"
+#define NUM_OF_L3_MASTERS ARRAY_SIZE(l3_masters)
+
+static void l3_dump_targ_context(u32 baseaddr)
+{
+ pr_err("COREREG : 0x%08x\n", readl(baseaddr + L3_COREREG));
+ pr_err("VERSIONREG : 0x%08x\n", readl(baseaddr + L3_VERSIONREG));
+ pr_err("MAINCTLREG : 0x%08x\n", readl(baseaddr + L3_MAINCTLREG));
+ pr_err("NTTPADDR_0 : 0x%08x\n", readl(baseaddr + L3_NTTPADDR_0));
+ pr_err("SVRTSTDLVL : 0x%08x\n", readl(baseaddr + L3_SVRTSTDLVL));
+ pr_err("SVRTCUSTOMLVL: 0x%08x\n", readl(baseaddr + L3_SVRTCUSTOMLVL));
+ pr_err("MAIN : 0x%08x\n", readl(baseaddr + L3_MAIN));
+ pr_err("HDR : 0x%08x\n", readl(baseaddr + L3_HDR));
+ pr_err("MSTADDR : 0x%08x\n", readl(baseaddr + L3_MSTADDR));
+ pr_err("SLVADDR : 0x%08x\n", readl(baseaddr + L3_SLVADDR));
+ pr_err("INFO : 0x%08x\n", readl(baseaddr + L3_INFO));
+ pr_err("SLVOFSLSB : 0x%08x\n", readl(baseaddr + L3_SLVOFSLSB));
+ pr_err("SLVOFSMSB : 0x%08x\n", readl(baseaddr + L3_SLVOFSMSB));
+ pr_err("CUSTOMINFO_INFO : 0x%08x\n", readl(baseaddr + L3_CUSTOMINFO_INFO));
+ pr_err("CUSTOMINFO_MSTADDR: 0x%08x\n", readl(baseaddr + L3_CUSTOMINFO_MSTADDR));
+ pr_err("CUSTOMINFO_OPCODE : 0x%08x\n", readl(baseaddr + L3_CUSTOMINFO_OPCODE));
+ pr_err("ADDRSPACESIZELOG : 0x%08x\n", readl(baseaddr + L3_ADDRSPACESIZELOG));
+}
+
/*
* Interrupt Handler for L3 error detection.
* 1) Identify the L3 clockdomain partition to which the error belongs to.
@@ -56,10 +79,10 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
{
struct omap4_l3 *l3 = _l3;
- int inttype, i, j;
+ int inttype, i, j, k;
int err_src = 0;
u32 std_err_main_addr, std_err_main, err_reg;
- u32 base, slave_addr, clear;
+ u32 base, slave_addr, clear, regoffset, masterid;
char *source_name;
/* Get the Type of interrupt */
@@ -88,11 +111,16 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
case STANDARD_ERROR:
source_name =
l3_targ_stderrlog_main_name[i][err_src];
+ regoffset = targ_reg_offset[i][err_src];
slave_addr = std_err_main_addr +
L3_SLAVE_ADDRESS_OFFSET;
+
WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
source_name, readl(slave_addr));
+
+ l3_dump_targ_context(base + regoffset);
+
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
writel(clear, std_err_main_addr);
@@ -101,9 +129,29 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
case CUSTOM_ERROR:
source_name =
l3_targ_stderrlog_main_name[i][err_src];
+ regoffset = targ_reg_offset[i][err_src];
WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
source_name);
+
+ masterid = readl(base + regoffset +
+ L3_CUSTOMINFO_MSTADDR);
+
+ for (k = 0;
+ k < NUM_OF_L3_MASTERS;
+ k++) {
+ if (masterid == l3_masters[k].id) {
+ pr_err("Master 0x%x %10s\n",
+ masterid,
+ l3_masters[k].name);
+ pr_err("%s OPCODE 0x%08x\n",
+ source_name,
+ readl(base + regoffset +
+ L3_CUSTOMINFO_OPCODE));
+ break;
+ }
+ }
+
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
writel(clear, std_err_main_addr);
diff --git a/arch/arm/mach-omap2/omap_l3_noc.h b/arch/arm/mach-omap2/omap_l3_noc.h
index 359b833..56d6b0a 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.h
+++ b/arch/arm/mach-omap2/omap_l3_noc.h
@@ -37,6 +37,24 @@
#define L3_APPLICATION_ERROR 0x0
#define L3_DEBUG_ERROR 0x1
+#define L3_COREREG 0x00
+#define L3_VERSIONREG 0x04
+#define L3_MAINCTLREG 0x08
+#define L3_NTTPADDR_0 0x10
+#define L3_SVRTSTDLVL 0x40
+#define L3_SVRTCUSTOMLVL 0x44
+#define L3_MAIN 0x48
+#define L3_HDR 0x4C
+#define L3_MSTADDR 0x50
+#define L3_SLVADDR 0x54
+#define L3_INFO 0x58
+#define L3_SLVOFSLSB 0x5C
+#define L3_SLVOFSMSB 0x60
+#define L3_CUSTOMINFO_INFO 0x64
+#define L3_CUSTOMINFO_MSTADDR 0x68
+#define L3_CUSTOMINFO_OPCODE 0x6C
+#define L3_ADDRSPACESIZELOG 0x80
+
u32 l3_flagmux[L3_MODULES] = {
0x50C,
0x100C,
@@ -79,6 +97,34 @@ u32 l3_targ_stderrlog_main_clk3[] = {
0x0148 /* EMUSS */
};
+struct l3_masters_data {
+ u32 id;
+ char name[15];
+};
+
+struct l3_masters_data l3_masters[] = {
+ { 0x0 , "MPU"},
+ { 0x10, "CS_ADP"},
+ { 0x14, "Unknown"},
+ { 0x20, "DSP"},
+ { 0x30, "IVAHD"},
+ { 0x40, "ISS"},
+ { 0x44, "DucatiM3"},
+ { 0x48, "FaceDetect"},
+ { 0x50, "SDMA_Rd"},
+ { 0x54, "SDMA_Wr"},
+ { 0x58, "Unknown"},
+ { 0x5C, "Unknown"},
+ { 0x60, "SGX"},
+ { 0x70, "DSS"},
+ { 0x80, "C2C"},
+ { 0x88, "Unknown"},
+ { 0x8C, "Unknown"},
+ { 0x90, "HSI"},
+ { 0xA0, "MMC1"},
+ { 0xA4, "MMC2"},
+};
+
char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
{
"DMM1",
@@ -112,6 +158,39 @@ char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
},
};
+u32 targ_reg_offset[L3_MODULES][18] = {
+ {
+ 0x100,
+ 0x200,
+ 0x300,
+ 0x400,
+ 0x0,
+ },
+ {
+ 0x500,
+ 0x300,
+ 0x100,
+ 0x400,
+ 0x700,
+ 0x000,
+ 0x000,
+ 0x000,
+ 0x000,
+ 0x600,
+ 0x800,
+ 0x000,
+ 0x000,
+ 0x000,
+ 0x000,
+ 0x100,
+ 0xA00,
+ 0xB00,
+ },
+ {
+ 0x000000
+ },
+};
+
u32 *l3_targ[L3_MODULES] = {
l3_targ_stderrlog_main_clk1,
l3_targ_stderrlog_main_clk2,
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
index c784c12..37d16e1 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, \
@@ -71,12 +75,14 @@ struct omap_opp_def {
* Initialization wrapper used to define SmartReflex process data
* XXX Is this needed? Just use C99 initializers in data files?
*/
-#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \
+#define VOLT_DATA_DEFINE(_v_nom, _v_margin, _efuse_offs, _errminlimit, _errgain, _abb_type) \
{ \
.volt_nominal = _v_nom, \
+ .volt_margin = _v_margin, \
.sr_efuse_offs = _efuse_offs, \
.sr_errminlimit = _errminlimit, \
- .vp_errgain = _errgain \
+ .vp_errgain = _errgain, \
+ .abb_type = _abb_type, \
}
/* Use this to initialize the default table */
@@ -86,11 +92,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_pmic.c b/arch/arm/mach-omap2/omap_pmic.c
new file mode 100644
index 0000000..3271bfe
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_pmic.c
@@ -0,0 +1,105 @@
+/*
+ * 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 <linux/string.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
+ * @desc: description for this PMIC.
+ */
+int __init omap_pmic_register_data(struct omap_pmic_map *omap_pmic_maps,
+ struct omap_pmic_description *desc)
+{
+ 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;
+
+ /* The base PMIC is the one controlling core voltdm */
+ if (desc && !strcmp(map->name, "core"))
+ omap_pm_set_pmic_lp_time(desc->pmic_lp_tstart,
+ desc->pmic_lp_tshut);
+
+ 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;
+}
+
+int __init omap_pmic_update(struct omap_pmic_map *tmp_map, char *name,
+ u32 old_chip_id, u32 new_chip_id)
+{
+ while (tmp_map->name != NULL) {
+ if (!strcmp(tmp_map->name, name) &&
+ (tmp_map->omap_chip.oc & new_chip_id)) {
+ WARN(1, "%s: this map already exists:%s-%x\n",
+ __func__, name, new_chip_id);
+ return -1;
+ }
+ if (!strcmp(tmp_map->name, name) &&
+ (tmp_map->omap_chip.oc & old_chip_id))
+ break;
+ tmp_map++;
+ }
+ if (tmp_map->name != NULL) {
+ tmp_map->omap_chip.oc = new_chip_id;
+ return 0;
+ }
+ return -ENOENT;
+}
diff --git a/arch/arm/mach-omap2/omap_tps6236x.c b/arch/arm/mach-omap2/omap_tps6236x.c
new file mode 100644
index 0000000..c369d7a
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_tps6236x.c
@@ -0,0 +1,434 @@
+/*
+ * 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_REG_SYSEN_CFG_TRANS 0xB4
+#define TWL6030_REG_VCORE3_CFG_GRP 0x5E
+#define TWL6030_REG_VMEM_CFG_GRP 0x64
+#define TWL6030_REG_MSK_TRANSITION 0x20
+#define TWL6030_BIT_APE_GRP BIT(0)
+#define TWL6030_BIT_CON_GRP BIT(1)
+#define TWL6030_BIT_MOD_GRP BIT(2)
+#define TWL6030_MSK_PREQ1 BIT(5)
+#define TWL6030_MSK_SYSEN_OFF (0x3 << 4)
+#define TWL6030_MSK_SYSEN_SLEEP (0x3 << 2)
+#define TWL6030_MSK_SYSEN_ACTIVE (0x3 << 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 = 32000,
+ .step_size = STEP_SIZE_TPS6236X,
+ .on_volt = 1375000,
+ .onlp_volt = 1375000,
+ .ret_volt = 830000,
+ .off_volt = 0,
+ .volt_setup_time = 0,
+ .switch_on_time = 1000,
+ .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,
+};
+
+/* As per SLVSAU9 */
+static __initdata struct omap_pmic_description tps_pmic_desc = {
+ .pmic_lp_tshut = 1, /* T-OFF 1ns rounded */
+ .pmic_lp_tstart = 1000, /* T-start */
+};
+/**
+ * _twl_i2c_rmw_u8() - Tiny helper function to do a read modify write for twl
+ * @mod_no: module number
+ * @mask: mask for the val
+ * @value: value to write
+ * @reg: register to write to
+ */
+static int __init _twl_i2c_rmw_u8(u8 mod_no, u8 mask, u8 value, u8 reg)
+{
+ int ret;
+ u8 val;
+
+ ret = twl_i2c_read_u8(mod_no, &val, reg);
+ if (ret)
+ goto out;
+
+ val &= ~mask;
+ val |= (value & mask);
+
+ ret = twl_i2c_write_u8(mod_no, val, reg);
+out:
+ return ret;
+}
+
+/**
+ * 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;
+ int ret1;
+ 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;
+
+ /* We would like to ramp down the voltage asap as well*/
+ val |= REG_TPS6236X_RAMP_CTRL_EN_DISC;
+
+ 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
+
+ /* unmask PREQ transition Executes ACT2SLP and SLP2ACT sleep sequence */
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_PREQ1,
+ 0x00, TWL6030_REG_MSK_TRANSITION);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030: map APE PREQ1(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+
+ /* Setup SYSEN to be 1 on Active and 0 for sleep and OFF states */
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_SYSEN_ACTIVE,
+ 0x01, TWL6030_REG_SYSEN_CFG_TRANS);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030: sysen active(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_SYSEN_SLEEP,
+ 0x00, TWL6030_REG_SYSEN_CFG_TRANS);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030: sysen sleep(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_SYSEN_OFF,
+ 0x00, TWL6030_REG_SYSEN_CFG_TRANS);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030: sysen off(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+
+ /* Map up SYSEN on TWL core to control TPS */
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_BIT_APE_GRP |
+ TWL6030_BIT_MOD_GRP | TWL6030_BIT_CON_GRP,
+ TWL6030_BIT_APE_GRP, TWL6030_REG_SYSEN_CFG_GRP);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030: map APE SYEN(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+
+ /* Since we dont use VCORE3, this should not be associated with APE */
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_BIT_APE_GRP,
+ 0x00, TWL6030_REG_VCORE3_CFG_GRP);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030:unmap APE VCORE3(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+
+ /* Since we dont use VMEM, this should not be associated with APE */
+ ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_BIT_APE_GRP,
+ 0x00, TWL6030_REG_VMEM_CFG_GRP);
+ if (ret1) {
+ pr_err("%s:Err:TWL6030: unmap APE VMEM(%d)\n", __func__, ret1);
+ ret = ret1;
+ }
+#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, &tps_pmic_desc);
+}
+
+/**
+ * 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;
+}
+
+int __init omap_tps6236x_update(char *name, u32 old_chip_id, u32 new_chip_id)
+{
+ return omap_pmic_update(omap_tps_map, name, old_chip_id, new_chip_id);
+}
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 07d6140..2d00a0c 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -30,32 +30,31 @@
#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
+
+#define TWL6030_REG_VCORE1_CFG_GRP 0x52
+#define TWL6030_REG_VCORE1_CFG_TRANS 0x53
+#define TWL6030_REG_VCORE2_CFG_GRP 0x58
+#define TWL6030_REG_VCORE2_CFG_TRANS 0x59
+#define TWL6030_REG_VCORE3_CFG_GRP 0x5e
+#define TWL6030_REG_VCORE3_CFG_TRANS 0x5f
+#define TWL6030_BIT_APE_GRP BIT(0)
+/*
+ * Setup CFG_TRANS mode as follows:
+ * 0x00 (OFF) when in OFF state(bit offset 4) and in sleep (bit offset 2)
+ * 0x01 (PWM/PFM Auto) when in ACTive state (bit offset 0)
+ * Dont trust Bootloader or reset values to set them up for kernel.
+ */
+#define TWL6030_REG_VCOREx_CFG_TRANS_MODE (0x00 << 4 | \
+ 0x00 << 2 | \
+ 0x01 << 0)
+#define TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC "OFF=OFF SLEEP=OFF ACT=AUTO"
static bool is_offset_valid;
static u8 smps_offset;
@@ -69,6 +68,55 @@ static bool __initdata twl_sr_enable_autoinit;
#define REG_SMPS_OFFSET 0xE0
#define SMARTREFLEX_ENABLE BIT(3)
+/**
+ * struct twl_reg_setup_array - NULL terminated array giving configuration
+ * @addr: reg address to write to
+ * @val: value to write with
+ * @desc: description of this reg for error printing
+ * NOTE: a NULL pointer in this indicates end of array.
+ *
+ * VCORE register configurations as per need.
+ */
+struct twl_reg_setup_array {
+ u8 addr;
+ u8 val;
+ char *desc;
+};
+
+/**
+ * _twl_set_regs() - helper to setup a config array
+ * @gendesc: generic description - used with error message
+ * @sarray: NULL terminated array of configuration values
+ *
+ * Configures TWL with a set of values terminated. If any write fails,
+ * this continues till the last and returns back with the last error
+ * value.
+ */
+static int __init _twl_set_regs(char *gendesc,
+ struct twl_reg_setup_array *sarray)
+{
+ int i = 0;
+ int ret1;
+ int ret = 0;
+
+ while (sarray->desc) {
+ ret1 = twl_i2c_write_u8(TWL6030_MODULE_ID0,
+ sarray->val,
+ sarray->addr);
+ if (ret1) {
+ pr_err("%s: %s: failed(%d), array index=%d, desc=%s, "
+ "reg=0x%02x, val=0x%02x\n",
+ __func__, gendesc, ret1, i,
+ sarray->desc, sarray->addr, sarray->val);
+ ret = ret1;
+ }
+ sarray++;
+ i++;
+ }
+
+ return ret;
+}
+
static unsigned long twl4030_vsel_to_uv(const u8 vsel)
{
return (((vsel * 125) + 6000)) * 100;
@@ -95,6 +143,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 +156,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 +177,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 +186,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 +215,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,19 +236,21 @@ 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 = {
- .slew_rate = 4000,
- .step_size = 12500,
- .on_volt = 1350000,
- .onlp_volt = 1350000,
- .ret_volt = 837500,
- .off_volt = 600000,
+static struct omap_voltdm_pmic omap443x_mpu_pmic = {
+ .slew_rate = 9000,
+ .step_size = 12660,
+ .on_volt = 1375000,
+ .onlp_volt = 1375000,
+ .ret_volt = 830000,
+ .off_volt = 0,
.volt_setup_time = 0,
+ .switch_on_time = 549,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
@@ -198,19 +258,26 @@ 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 = {
- .slew_rate = 4000,
- .step_size = 12500,
- .on_volt = 1100000,
- .onlp_volt = 1100000,
- .ret_volt = 837500,
- .off_volt = 600000,
+static struct omap_voltdm_pmic omap4_iva_pmic = {
+ .slew_rate = 9000,
+ .step_size = 12660,
+ .on_volt = 1188000,
+ .onlp_volt = 1188000,
+ .ret_volt = 830000,
+ .off_volt = 0,
.volt_setup_time = 0,
+ .switch_on_time = 549,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
@@ -218,19 +285,26 @@ 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 = {
- .slew_rate = 4000,
- .step_size = 12500,
- .on_volt = 1100000,
- .onlp_volt = 1100000,
- .ret_volt = 837500,
- .off_volt = 600000,
+static struct omap_voltdm_pmic omap443x_core_pmic = {
+ .slew_rate = 9000,
+ .step_size = 12660,
+ .on_volt = 1200000,
+ .onlp_volt = 1200000,
+ .ret_volt = 830000,
+ .off_volt = 0,
.volt_setup_time = 0,
+ .switch_on_time = 549,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
@@ -238,43 +312,49 @@ 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 = 9000,
+ .step_size = 12660,
+ .on_volt = 1200000,
+ .onlp_volt = 1200000,
+ .ret_volt = 830000,
+ /* OMAP4 + TWL + TPS limitation keep off_volt same as ret_volt */
+ .off_volt = 830000,
+ .volt_setup_time = 0,
+ .switch_on_time = 549,
+ .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 +366,144 @@ 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;
+}
+
+
+/* OMAP4430 - All vcores: 1, 2 and 3 should go down with PREQ */
+static __initdata struct twl_reg_setup_array omap4430_twl6030_setup[] = {
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE1 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE1" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE2 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE2" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ {
+ .addr = TWL6030_REG_VCORE3_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE3 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE3_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE3" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ { .desc = NULL} /* TERMINATOR */
+};
- voltdm = omap_voltage_domain_lookup("mpu");
- omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
+static int __init twl_set_4430vcore(struct voltagedomain *voltdm)
+{
+ return _twl_set_regs("OMAP4430 ", omap4430_twl6030_setup);
+}
- voltdm = omap_voltage_domain_lookup("core");
- omap_voltage_register_pmic(voltdm, &omap3_core_volt_info);
+/* OMAP4460 - VCORE3 is unused, 1 and 2 should go down with PREQ */
+static __initdata struct twl_reg_setup_array omap4460_twl6030_setup[] = {
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE1 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE1" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE2 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE2" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ { .desc = NULL} /* TERMINATOR */
+};
- return 0;
+static int __init twl_set_4460vcore(struct voltagedomain *voltdm)
+{
+ return _twl_set_regs("OMAP4460 ", omap4460_twl6030_setup);
+}
+
+#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,
+ .special_action = twl_set_4430vcore,
+ },
+ {
+ .name = "core",
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X),
+ .pmic_data = &omap446x_core_pmic,
+ .special_action = twl_set_4460vcore,
+ },
+ {
+ .name = "iva",
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+ .pmic_data = &omap4_iva_pmic,
+ },
+ /* Terminator */
+ { .name = NULL, .pmic_data = NULL},
+};
+
+/* As per SWCS045 */
+static __initdata struct omap_pmic_description twl6030_pmic_desc = {
+ .pmic_lp_tshut = 500, /* T-OFF */
+ .pmic_lp_tstart = 500, /* T-ON */
+};
+
+int __init omap_twl_init(void)
+{
+ struct omap_pmic_description *desc = NULL;
+
+ /* 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;
+ }
+ if (cpu_is_omap44xx())
+ desc = &twl6030_pmic_desc;
+
+ return omap_pmic_register_data(omap_twl_map, desc);
}
/**
@@ -337,3 +546,8 @@ err:
pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
return ret;
}
+
+int __init omap_twl_pmic_update(char *name, u32 old_chip_id, u32 new_chip_id)
+{
+ return omap_pmic_update(omap_twl_map, name, old_chip_id, new_chip_id);
+}
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index 0627494..1858712 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -18,10 +18,13 @@
*/
#include <linux/module.h>
#include <linux/opp.h>
+#include <linux/clk.h>
#include <plat/omap_device.h>
+#include <plat/clock.h>
#include "omap_opp_data.h"
+#include "dvfs.h"
/* Temp variable to allow multiple calls */
static u8 __initdata omap_table_init;
@@ -38,6 +41,8 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
u32 opp_def_size)
{
int i, r;
+ struct clk *clk;
+ long round_rate;
if (!opp_def || !opp_def_size) {
pr_err("%s: invalid params!\n", __func__);
@@ -58,19 +63,34 @@ 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);
+ continue;
}
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;
+ continue;
}
dev = &oh->od->pdev.dev;
+ clk = omap_clk_get_by_name(opp_def->clk_name);
+ if (clk) {
+ round_rate = clk_round_rate(clk, opp_def->freq);
+ if (round_rate > 0) {
+ opp_def->freq = round_rate;
+ } else {
+ WARN(1, "%s: round_rate for clock %s failed\n",
+ __func__, opp_def->clk_name);
+ continue; /* skip Bad OPP */
+ }
+ } else {
+ WARN(1, "%s: No clock by name %s found\n", __func__,
+ opp_def->clk_name);
+ continue; /* skip Bad OPP */
+ }
r = opp_add(dev, opp_def->freq, opp_def->u_volt);
if (r) {
dev_err(dev, "%s: add OPP %ld failed for %s [%d] "
@@ -85,6 +105,12 @@ 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);
}
}
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index d95f3f9..41619ea 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -36,12 +36,12 @@
#define OMAP3430_VDD_MPU_OPP5_UV 1350000
struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
- VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, 0, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, 0, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, 0, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, 0, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, 0, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
};
/* VDD2 */
@@ -51,10 +51,28 @@ struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
#define OMAP3430_VDD_CORE_OPP3_UV 1150000
struct omap_volt_data omap34xx_vddcore_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, 0, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, 0, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, 0, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(0, 0, 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 */
@@ -67,11 +85,11 @@ struct omap_volt_data omap34xx_vddcore_volt_data[] = {
#define OMAP3630_VDD_MPU_OPP1G_UV 1375000
struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
- VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, 0, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, 0, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, 0, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, 0, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27, OMAP_ABB_FAST_OPP),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
};
/* VDD2 */
@@ -80,24 +98,24 @@ struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
#define OMAP3630_VDD_CORE_OPP100_UV 1200000
struct omap_volt_data omap36xx_vddcore_volt_data[] = {
- VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
- VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, 0, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, 0, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
};
/* OPP 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..e36ca46 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
@@ -19,8 +19,10 @@
* GNU General Public License for more details.
*/
#include <linux/module.h>
+#include <linux/opp.h>
#include <plat/cpu.h>
+#include <plat/common.h>
#include "control.h"
#include "omap_opp_data.h"
@@ -33,60 +35,276 @@
#define OMAP4430_VDD_MPU_OPP50_UV 1025000
#define OMAP4430_VDD_MPU_OPP100_UV 1200000
-#define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000
-#define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000
+#define OMAP4430_VDD_MPU_OPPTURBO_UV 1325000
+#define OMAP4430_VDD_MPU_OPPNITRO_UV 1388000
-struct omap_volt_data omap44xx_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),
- VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
+struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27, OMAP_ABB_FAST_OPP),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
};
-#define OMAP4430_VDD_IVA_OPP50_UV 1013000
-#define OMAP4430_VDD_IVA_OPP100_UV 1188000
-#define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000
+#define OMAP4430_VDD_IVA_OPP50_UV 950000
+#define OMAP4430_VDD_IVA_OPP100_UV 1114000
+#define OMAP4430_VDD_IVA_OPPTURBO_UV 1291000
-struct omap_volt_data omap44xx_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),
- VOLT_DATA_DEFINE(0, 0, 0, 0),
+struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, 0, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, 0, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, 0, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
};
-#define OMAP4430_VDD_CORE_OPP50_UV 1025000
-#define OMAP4430_VDD_CORE_OPP100_UV 1200000
+#define OMAP4430_VDD_CORE_OPP50_UV 962000
+#define OMAP4430_VDD_CORE_OPP100_UV 1127000
-struct omap_volt_data omap44xx_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),
+struct omap_volt_data omap443x_vdd_core_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, 0, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, 0, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(0, 0, 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_OPP100_UV),
+ /* FDIF OPP1 - OPP25 */
+ OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 32000000, OMAP4430_VDD_CORE_OPP50_UV),
+ /* FDIF OPP2 - OPP50 */
+ OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 64000000, OMAP4430_VDD_CORE_OPP50_UV),
+ /* FDIF OPP3 - OPP100 */
+ OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 128000000, OMAP4430_VDD_CORE_OPP100_UV),
+ /* DSP OPP1 - OPP50 */
+ OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", true, 232750000, OMAP4430_VDD_IVA_OPP50_UV),
+ /* DSP OPP2 - OPP100 */
+ OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", true, 465500000, OMAP4430_VDD_IVA_OPP100_UV),
+ /* DSP OPP3 - OPPTB */
+ OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", false, 496000000, OMAP4430_VDD_IVA_OPPTURBO_UV),
+ /* HSI OPP1 - OPP50 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4430_VDD_CORE_OPP50_UV),
+ /* HSI OPP2 - OPP100 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4430_VDD_CORE_OPP100_UV),
+ /* ABE OPP1 - OPP50 */
+ OPP_INITIALIZER("aess", "abe_clk", "iva", true, 98304000, OMAP4430_VDD_IVA_OPP50_UV),
+ /* ABE OPP2 - OPP100 */
+ OPP_INITIALIZER("aess", "abe_clk", "iva", true, 196608000, OMAP4430_VDD_IVA_OPP100_UV),
+};
+
+#define OMAP4460_VDD_MPU_OPP50_UV 1025000
+#define OMAP4460_VDD_MPU_OPP100_UV 1203000
+#define OMAP4460_VDD_MPU_OPPTURBO_UV 1317000
+#define OMAP4460_VDD_MPU_OPPNITRO_UV 1380000
+
+struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, 10000, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, 0, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27, OMAP_ABB_FAST_OPP),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_IVA_OPP50_UV 950000
+#define OMAP4460_VDD_IVA_OPP100_UV 1140000
+#define OMAP4460_VDD_IVA_OPPTURBO_UV 1291000
+#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, 13000, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, 0, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, 0, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, 0, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23, OMAP_ABB_FAST_OPP),
+ VOLT_DATA_DEFINE(0, 0, 0, 0, 0, 0),
};
+#define OMAP4460_VDD_CORE_OPP50_UV 962000
+#define OMAP4460_VDD_CORE_OPP100_UV 1127000
+#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, 38000, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, 13000, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, 13000, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16, OMAP_ABB_NONE),
+ VOLT_DATA_DEFINE(0, 0, 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 */
+ 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),
+ OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 200000000, OMAP4460_VDD_CORE_OPP100_OV_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", false, 384000000, OMAP4460_VDD_CORE_OPP100_OV_UV),
+ /* FDIF OPP1 - OPP25 */
+ OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 32000000, OMAP4460_VDD_CORE_OPP50_UV),
+ /* FDIF OPP2 - OPP50 */
+ OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 64000000, OMAP4460_VDD_CORE_OPP50_UV),
+ /* FDIF OPP3 - OPP100 */
+ OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 128000000, OMAP4460_VDD_CORE_OPP100_UV),
+ /* DSP OPP1 - OPP50 */
+ OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", true, 232750000, OMAP4460_VDD_IVA_OPP50_UV),
+ /* DSP OPP2 - OPP100 */
+ OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", true, 465500000, OMAP4460_VDD_IVA_OPP100_UV),
+ /* DSP OPP3 - OPPTB */
+ OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", false, 496000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
+ /* HSI OPP1 - OPP50 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4460_VDD_CORE_OPP50_UV),
+ /* HSI OPP2 - OPP100 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4460_VDD_CORE_OPP100_UV),
+ /* ABE OPP1 - OPP50 */
+ OPP_INITIALIZER("aess", "abe_clk", "iva", true, 98304000, OMAP4460_VDD_IVA_OPP50_UV),
+ /* ABE OPP2 - OPP100 */
+ OPP_INITIALIZER("aess", "abe_clk", "iva", true, 196608000, OMAP4460_VDD_IVA_OPP100_UV),
+};
+
+/**
+ * omap4_mpu_opp_enable() - helper to enable the OPP
+ * @freq: frequency to enable
+ */
+static void __init omap4_mpu_opp_enable(unsigned long freq)
+{
+ struct device *mpu_dev;
+ int r;
+
+ mpu_dev = omap2_get_mpuss_device();
+ if (!mpu_dev) {
+ pr_err("%s: no mpu_dev, did not enable f=%ld\n", __func__,
+ freq);
+ return;
+ }
+
+ r = opp_enable(mpu_dev, freq);
+ if (r < 0)
+ dev_err(mpu_dev, "%s: opp_enable failed(%d) f=%ld\n", __func__,
+ r, freq);
+}
+
/**
* omap4_opp_init() - initialize omap4 opp table
*/
@@ -96,9 +314,19 @@ int __init omap4_opp_init(void)
if (!cpu_is_omap44xx())
return r;
+ 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));
- r = omap_init_opp_table(omap44xx_opp_def_list,
- ARRAY_SIZE(omap44xx_opp_def_list));
+ if (!r) {
+ if (omap4_has_mpu_1_2ghz())
+ omap4_mpu_opp_enable(1200000000);
+ if (omap4_has_mpu_1_5ghz())
+ omap4_mpu_opp_enable(1500000000);
+ }
return r;
}
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index e01da45..5942d23 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -38,11 +38,27 @@
#include "prm2xxx_3xxx.h"
#include "pm.h"
+#define PM_DEBUG_MAX_SAVED_REGS 64
+#define PM_DEBUG_PRM_MIN 0x4A306000
+#define PM_DEBUG_PRM_MAX (0x4A307F00 + (PM_DEBUG_MAX_SAVED_REGS * 4) - 1)
+#define PM_DEBUG_CM1_MIN 0x4A004000
+#define PM_DEBUG_CM1_MAX (0x4A004F00 + (PM_DEBUG_MAX_SAVED_REGS * 4) - 1)
+#define PM_DEBUG_CM2_MIN 0x4A008000
+#define PM_DEBUG_CM2_MAX (0x4A009F00 + (PM_DEBUG_MAX_SAVED_REGS * 4) - 1)
+
int omap2_pm_debug;
u32 enable_off_mode;
u32 sleep_while_idle;
u32 wakeup_timer_seconds;
u32 wakeup_timer_milliseconds;
+u32 omap4_device_off_counter = 0;
+
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+static u32 saved_reg_num;
+static u32 saved_reg_num_used;
+static u32 saved_reg_addr;
+static u32 saved_reg_buff[2][PM_DEBUG_MAX_SAVED_REGS];
+#endif
#define DUMP_PRM_MOD_REG(mod, reg) \
regs[reg_count].name = #mod "." #reg; \
@@ -194,6 +210,8 @@ static int pm_dbg_init(void);
enum {
DEBUG_FILE_COUNTERS = 0,
DEBUG_FILE_TIMERS,
+ DEBUG_FILE_LAST_COUNTERS,
+ DEBUG_FILE_LAST_TIMERS,
};
struct pm_module_def {
@@ -367,7 +385,7 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
/* Update timer for previous state */
t = sched_clock();
- pwrdm->state_timer[prev] += t - pwrdm->timer;
+ pwrdm->time.state[prev] += t - pwrdm->timer;
pwrdm->timer = t;
}
@@ -389,10 +407,53 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
return 0;
}
+static int pwrdm_dbg_show_count_stats(struct powerdomain *pwrdm,
+ struct powerdomain_count_stats *stats, struct seq_file *s)
+{
+ int i;
+
+ seq_printf(s, "%s (%s)", pwrdm->name,
+ pwrdm_state_names[pwrdm->state]);
+
+ for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+ seq_printf(s, ",%s:%d", pwrdm_state_names[i],
+ stats->state[i]);
+
+ seq_printf(s, ",RET-LOGIC-OFF:%d", stats->ret_logic_off);
+ for (i = 0; i < pwrdm->banks; i++)
+ seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
+ stats->ret_mem_off[i]);
+
+ seq_printf(s, "\n");
+
+ return 0;
+}
+
+static int pwrdm_dbg_show_time_stats(struct powerdomain *pwrdm,
+ struct powerdomain_time_stats *stats, struct seq_file *s)
+{
+ int i;
+ u64 total = 0;
+
+ seq_printf(s, "%s (%s)", pwrdm->name,
+ pwrdm_state_names[pwrdm->state]);
+
+ for (i = 0; i < 4; i++)
+ total += stats->state[i];
+
+ for (i = 0; i < 4; i++)
+ seq_printf(s, ",%s:%lld (%lld%%)", pwrdm_state_names[i],
+ stats->state[i],
+ total ? div64_u64(stats->state[i] * 100, total) : 0);
+
+ seq_printf(s, "\n");
+
+ return 0;
+}
+
static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
{
struct seq_file *s = (struct seq_file *)user;
- int i;
if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
@@ -403,25 +464,31 @@ static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
- seq_printf(s, "%s (%s)", pwrdm->name,
- pwrdm_state_names[pwrdm->state]);
- for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
- seq_printf(s, ",%s:%d", pwrdm_state_names[i],
- pwrdm->state_counter[i]);
+ pwrdm_dbg_show_count_stats(pwrdm, &pwrdm->count, s);
- seq_printf(s, ",RET-LOGIC-OFF:%d", pwrdm->ret_logic_off_counter);
- for (i = 0; i < pwrdm->banks; i++)
- seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
- pwrdm->ret_mem_off_counter[i]);
+ return 0;
+}
- seq_printf(s, "\n");
+static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
+{
+ struct seq_file *s = (struct seq_file *)user;
+
+ if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
+ strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
+ strncmp(pwrdm->name, "dpll", 4) == 0)
+ return 0;
+
+ pwrdm_state_switch(pwrdm);
+
+ pwrdm_dbg_show_time_stats(pwrdm, &pwrdm->time, s);
return 0;
}
-static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
+static int pwrdm_dbg_show_last_counter(struct powerdomain *pwrdm, void *user)
{
struct seq_file *s = (struct seq_file *)user;
+ struct powerdomain_count_stats stats;
int i;
if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
@@ -429,22 +496,42 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
strncmp(pwrdm->name, "dpll", 4) == 0)
return 0;
- pwrdm_state_switch(pwrdm);
+ stats = pwrdm->count;
+ for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+ stats.state[i] -= pwrdm->last_count.state[i];
+ for (i = 0; i < PWRDM_MAX_MEM_BANKS; i++)
+ stats.ret_mem_off[i] -= pwrdm->last_count.ret_mem_off[i];
+ stats.ret_logic_off -= pwrdm->last_count.ret_logic_off;
- seq_printf(s, "%s (%s)", pwrdm->name,
- pwrdm_state_names[pwrdm->state]);
+ pwrdm->last_count = pwrdm->count;
- for (i = 0; i < 4; i++)
- seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
- pwrdm->state_timer[i]);
+ pwrdm_dbg_show_count_stats(pwrdm, &stats, s);
+
+ return 0;
+}
+
+static int pwrdm_dbg_show_last_timer(struct powerdomain *pwrdm, void *user)
+{
+ struct seq_file *s = (struct seq_file *)user;
+ struct powerdomain_time_stats stats;
+ int i;
+
+ stats = pwrdm->time;
+ for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+ stats.state[i] -= pwrdm->last_time.state[i];
+
+ pwrdm->last_time = pwrdm->time;
+
+ pwrdm_dbg_show_time_stats(pwrdm, &stats, s);
- seq_printf(s, "\n");
return 0;
}
static int pm_dbg_show_counters(struct seq_file *s, void *unused)
{
pwrdm_for_each(pwrdm_dbg_show_counter, s);
+ if (cpu_is_omap44xx())
+ seq_printf(s, "DEVICE-OFF:%d\n", omap4_device_off_counter);
clkdm_for_each(clkdm_dbg_show_counter, s);
return 0;
@@ -456,6 +543,18 @@ static int pm_dbg_show_timers(struct seq_file *s, void *unused)
return 0;
}
+static int pm_dbg_show_last_counters(struct seq_file *s, void *unused)
+{
+ pwrdm_for_each(pwrdm_dbg_show_last_counter, s);
+ return 0;
+}
+
+static int pm_dbg_show_last_timers(struct seq_file *s, void *unused)
+{
+ pwrdm_for_each(pwrdm_dbg_show_last_timer, s);
+ return 0;
+}
+
static int pm_dbg_open(struct inode *inode, struct file *file)
{
switch ((int)inode->i_private) {
@@ -463,9 +562,15 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
return single_open(file, pm_dbg_show_counters,
&inode->i_private);
case DEBUG_FILE_TIMERS:
- default:
return single_open(file, pm_dbg_show_timers,
&inode->i_private);
+ case DEBUG_FILE_LAST_COUNTERS:
+ return single_open(file, pm_dbg_show_last_counters,
+ &inode->i_private);
+ case DEBUG_FILE_LAST_TIMERS:
+ default:
+ return single_open(file, pm_dbg_show_last_timers,
+ &inode->i_private);
};
}
@@ -488,7 +593,7 @@ static const struct file_operations debug_reg_fops = {
.release = single_release,
};
-int pm_dbg_regset_init(int reg_set)
+int __init pm_dbg_regset_init(int reg_set)
{
char name[2];
@@ -539,6 +644,47 @@ static int pwrdm_suspend_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
pwrdm_suspend_set, "%llu\n");
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+static bool is_addr_valid()
+{
+ int saved_reg_addr_max = 0;
+ /* Only for OMAP4 for the timebeing */
+ if (!cpu_is_omap44xx())
+ return false;
+
+ saved_reg_num = (saved_reg_num > PM_DEBUG_MAX_SAVED_REGS) ?
+ PM_DEBUG_MAX_SAVED_REGS : saved_reg_num;
+
+ saved_reg_addr_max = saved_reg_addr + (saved_reg_num * 4) - 1;
+
+ if (saved_reg_addr >= PM_DEBUG_PRM_MIN &&
+ saved_reg_addr_max <= PM_DEBUG_PRM_MAX)
+ return true;
+ if (saved_reg_addr >= PM_DEBUG_CM1_MIN &&
+ saved_reg_addr_max <= PM_DEBUG_CM1_MAX)
+ return true;
+ if (saved_reg_addr >= PM_DEBUG_CM2_MIN &&
+ saved_reg_addr_max <= PM_DEBUG_CM2_MAX)
+ return true;
+ return false;
+}
+
+void omap4_pm_suspend_save_regs()
+{
+ int i = 0;
+ if (!saved_reg_num || !is_addr_valid())
+ return;
+
+ saved_reg_num_used = saved_reg_num;
+
+ for (i = 0; i < saved_reg_num; i++) {
+ saved_reg_buff[1][i] = omap_readl(saved_reg_addr + (i*4));
+ saved_reg_buff[0][i] = saved_reg_addr + (i*4);
+ }
+ return;
+}
+#endif
+
static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
{
int i;
@@ -548,7 +694,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
t = sched_clock();
for (i = 0; i < 4; i++)
- pwrdm->state_timer[i] = 0;
+ pwrdm->time.state[i] = 0;
pwrdm->timer = t;
@@ -567,7 +713,19 @@ static int option_get(void *data, u64 *val)
{
u32 *option = data;
+ if (option == &enable_off_mode) {
+ enable_off_mode = off_mode_enabled;
+ }
+
*val = *option;
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+ if (option == &saved_reg_addr) {
+ int i;
+ for (i = 0; i < saved_reg_num_used; i++)
+ pr_info(" %x = %x\n", saved_reg_buff[0][i],
+ saved_reg_buff[1][i]);
+ }
+#endif
return 0;
}
@@ -579,7 +737,10 @@ static int option_set(void *data, u64 val)
if (option == &wakeup_timer_milliseconds && val >= 1000)
return -EINVAL;
- *option = val;
+ if (cpu_is_omap443x() && omap_type() == OMAP2_DEVICE_TYPE_GP)
+ *option = 0;
+ else
+ *option = val;
if (option == &enable_off_mode) {
if (val)
@@ -595,7 +756,7 @@ static int option_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
-static int pm_dbg_init(void)
+static int __init pm_dbg_init(void)
{
int i;
struct dentry *d;
@@ -604,9 +765,11 @@ static int 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;
}
@@ -619,9 +782,16 @@ static int pm_dbg_init(void)
d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
(void) debugfs_create_file("time", S_IRUGO,
d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
+ (void) debugfs_create_file("last_count", S_IRUGO,
+ d, (void *)DEBUG_FILE_LAST_COUNTERS, &debug_fops);
+ (void) debugfs_create_file("last_time", S_IRUGO,
+ d, (void *)DEBUG_FILE_LAST_TIMERS, &debug_fops);
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);
@@ -637,15 +807,29 @@ static int pm_dbg_init(void)
}
- (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
- &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:
+#ifdef CONFIG_OMAP_ALLOW_OSWR
+ (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
+ &enable_off_mode, &pm_dbg_option_fops);
+#endif
(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",
S_IRUGO | S_IWUSR, d, &wakeup_timer_milliseconds,
&pm_dbg_option_fops);
+
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+ (void) debugfs_create_file("saved_reg_show",
+ S_IRUGO | S_IWUSR, d, &saved_reg_addr,
+ &pm_dbg_option_fops);
+ debugfs_create_u32("saved_reg_addr", S_IRUGO | S_IWUGO, d,
+ &saved_reg_addr);
+ debugfs_create_u32("saved_reg_num", S_IRUGO | S_IWUGO, d,
+ &saved_reg_num);
+#endif
pm_dbg_init_done = 1;
return 0;
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 49486f5..4464039 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -24,30 +24,82 @@
#include "clockdomain.h"
#include "pm.h"
+/**
+ * struct omap2_pm_lp_description - Describe low power behavior of the system
+ * @oscillator_startup_time: Time rounded up to uSec for the oscillator to
+ * provide a stable clock from power on.
+ * @oscillator_shutdown_time: Time rounded up to uSec for oscillator to safely
+ * switch off.
+ * @pmic_startup_time: Time rounded up to uSec for the PMIC to
+ * provide be ready for operation from low power
+ * state. Note: this is not the same as voltage
+ * rampup time, instead, consider the PMIC to be
+ * in lowest power state(say OFF), this is the time
+ * required for it to become ready for it's DCDCs
+ * or LDOs to start operation.
+ * @pmic_shutdown_time: Time rounded up to uSec for the PMIC to
+ * go to low power after the LDOs are pulled to
+ * appropriate state. Note: this is not the same as
+ * voltage rampdown time, instead, consider the
+ * PMIC to have switched it's LDOs down, this is
+ * time taken to reach it's lowest power state(say
+ * sleep/OFF).
+ *
+ * With complex systems like OMAP, we need a generic description of system
+ * behavior beyond the normal description of device/peripheral operation
+ * which in conjunction with other parameters describe and control the low
+ * power operation of the device. This information tends to be specific
+ * to every board.
+ */
+struct omap2_pm_lp_description {
+ u32 oscillator_startup_time;
+ u32 oscillator_shutdown_time;
+ u32 pmic_startup_time;
+ u32 pmic_shutdown_time;
+};
+
+/*
+ * Setup time to be the max... we want to err towards the worst
+ * as default. rest of the system can populate these with more
+ * optimal values
+ */
+static struct omap2_pm_lp_description _pm_lp_desc = {
+ .oscillator_startup_time = ULONG_MAX,
+ .oscillator_shutdown_time = ULONG_MAX,
+ .pmic_startup_time = ULONG_MAX,
+ .pmic_shutdown_time = ULONG_MAX,
+};
+
static struct omap_device_pm_latency *pm_lats;
static struct device *mpu_dev;
static struct device *iva_dev;
static struct device *l3_dev;
static struct device *dsp_dev;
+static struct device *fdif_dev;
+
+bool omap_pm_is_ready_status;
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)
{
@@ -56,6 +108,89 @@ struct device *omap4_get_dsp_device(void)
}
EXPORT_SYMBOL(omap4_get_dsp_device);
+struct device *omap4_get_fdif_device(void)
+{
+ WARN_ON_ONCE(!fdif_dev);
+ return fdif_dev;
+}
+EXPORT_SYMBOL(omap4_get_fdif_device);
+
+/**
+ * omap_pm_get_pmic_lp_time() - retrieve the oscillator time
+ * @tstart: pointer to startup time in uSec
+ * @tshut: pointer to shutdown time in uSec
+ *
+ * if the pointers are invalid, returns error, else
+ * populates the tstart and tshut values with the currently
+ * stored values.
+ */
+int omap_pm_get_osc_lp_time(u32 *tstart, u32 *tshut)
+{
+ if (!tstart || !tshut)
+ return -EINVAL;
+
+ *tstart = _pm_lp_desc.oscillator_startup_time;
+ *tshut = _pm_lp_desc.oscillator_shutdown_time;
+
+ return 0;
+}
+
+/**
+ * omap_pm_get_pmic_lp_time() - retrieve the PMIC time
+ * @tstart: pointer to startup time in uSec
+ * @tshut: pointer to shutdown time in uSec
+ *
+ * if the pointers are invalid, returns error, else
+ * populates the tstart and tshut values with the currently
+ * stored values.
+ */
+int omap_pm_get_pmic_lp_time(u32 *tstart, u32 *tshut)
+{
+ if (!tstart || !tshut)
+ return -EINVAL;
+
+ *tstart = _pm_lp_desc.pmic_startup_time;
+ *tshut = _pm_lp_desc.pmic_shutdown_time;
+
+ return 0;
+}
+
+/**
+ * omap_pm_set_osc_lp_time() - setup the system oscillator time
+ * @tstart: startup time rounded up to uSec
+ * @tshut: shutdown time rounded up to uSec
+ *
+ * All boards do need an oscillator for the device to function.
+ * The startup and stop time of these oscillators vary. Populate
+ * from the board file to optimize the timing.
+ * This function is meant to be used at boot-time configuration.
+ *
+ * NOTE: This API is intended to be invoked from board file
+ */
+void __init omap_pm_set_osc_lp_time(u32 tstart, u32 tshut)
+{
+ _pm_lp_desc.oscillator_startup_time = tstart;
+ _pm_lp_desc.oscillator_shutdown_time = tshut;
+}
+
+/**
+ * omap_pm_set_pmic_lp_time() - setup the pmic low power time
+ * @tstart: startup time rounded up to uSec
+ * @tshut: shutdown time rounded up to uSec
+ *
+ * Store the time for PMIC to enter to lowest state supported.
+ * in the case of multiple PMIC on a platform, choose the one
+ * that ends the sequence for LP state such as OFF and starts
+ * the sequence such as wakeup from OFF - e.g. a PMIC that
+ * controls core-domain.
+ * This function is meant to be used at boot-time configuration.
+ */
+void __init omap_pm_set_pmic_lp_time(u32 tstart, u32 tshut)
+{
+ _pm_lp_desc.pmic_startup_time = tstart;
+ _pm_lp_desc.pmic_shutdown_time = tshut;
+}
+
/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
static int _init_omap_device(char *name, struct device **new_dev)
{
@@ -90,6 +225,7 @@ static void omap2_init_processor_devices(void)
_init_omap_device("l3_main_1", &l3_dev);
_init_omap_device("dsp", &dsp_dev);
_init_omap_device("iva", &iva_dev);
+ _init_omap_device("fdif", &fdif_dev);
} else {
_init_omap_device("l3_main", &l3_dev);
}
@@ -106,8 +242,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 +264,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 +280,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]);
@@ -160,6 +298,45 @@ err:
return ret;
}
+static int __init boot_volt_scale(struct voltagedomain *voltdm,
+ unsigned long boot_v)
+{
+ struct omap_volt_data *vdata;
+ int ret = 0;
+
+ vdata = omap_voltage_get_voltdata(voltdm, boot_v);
+ if (IS_ERR_OR_NULL(vdata)) {
+ pr_err("%s:%s: Bad New voltage data for %ld\n",
+ __func__, voltdm->name, boot_v);
+ return PTR_ERR(vdata);
+ }
+ /*
+ * DO NOT DO abb prescale -
+ * case 1: OPP needs FBB, bootloader configured FBB
+ * - doing a prescale results in bypass -> system fail
+ * case 2: OPP needs FBB, bootloader does not configure FBB
+ * - FBB will be configured in postscale
+ * case 3: OPP needs bypass, bootloader configures FBB
+ * - bypass will be configured in postscale
+ * case 4: OPP needs bypass, bootloader configured in bypass
+ * - bypass programming in postscale skipped
+ */
+ ret = voltdm_scale(voltdm, vdata);
+ if (ret) {
+ pr_err("%s: Fail set voltage(v=%ld)on vdd%s\n",
+ __func__, boot_v, voltdm->name);
+ return ret;
+ }
+ if (voltdm->abb) {
+ ret = omap_ldo_abb_post_scale(voltdm, vdata);
+ if (ret) {
+ pr_err("%s: Fail abb postscale(v=%ld)vdd%s\n",
+ __func__, boot_v, voltdm->name);
+ }
+ }
+ return ret;
+}
+
/*
* This API is to be called during init to put the various voltage
* domains to the voltage as per the opp table. Typically we boot up
@@ -174,14 +351,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 +373,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 = boot_volt_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 = boot_volt_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 +457,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 +466,12 @@ 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);
+ } else {
+ omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev);
+ }
+ omap2_set_init_voltage("core", "virt_l3_ck", l3_dev);
omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
}
@@ -251,9 +486,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..c9da6b9 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -17,10 +17,34 @@
extern void *omap3_secure_ram_storage;
extern void omap3_pm_off_mode_enable(int);
-extern void omap_sram_idle(void);
+extern void omap_sram_idle(bool suspend);
extern int omap3_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,
+ bool suspend);
+extern void omap4_trigger_ioctrl(void);
+extern u32 omap4_device_off_counter;
+
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+ return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+ return false;
+}
+#endif
#if defined(CONFIG_PM_OPP)
extern int omap3_opp_init(void);
@@ -36,6 +60,15 @@ static inline int omap4_opp_init(void)
}
#endif
+#ifdef CONFIG_PM
+int omap4_pm_cold_reset(char *reason);
+#else
+int omap4_pm_cold_reset(char *reason)
+{
+ return -EINVAL;
+}
+#endif
+
/*
* cpuidle mach specific parameters
*
@@ -68,15 +101,18 @@ extern struct omap_dm_timer *gptimer_wakeup;
extern void omap2_pm_dump(int mode, int resume, unsigned int us);
extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
extern int omap2_pm_debug;
-extern u32 enable_off_mode;
extern u32 sleep_while_idle;
#else
#define omap2_pm_dump(mode, resume, us) do {} while (0);
#define omap2_pm_wakeup_on_timer(seconds, milliseconds) do {} while (0);
#define omap2_pm_debug 0
-#define enable_off_mode 0
#define sleep_while_idle 0
#endif
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+extern void omap4_pm_suspend_save_regs(void);
+#else
+static inline void omap4_pm_suspend_save_regs(void) { }
+#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
@@ -125,19 +161,132 @@ 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 *);
+};
+
+/**
+ * struct omap_pmic_description - Describe low power behavior of the PMIC
+ * @pmic_lp_tshut: Time rounded up to uSec for the PMIC to
+ * go to low power after the LDOs are pulled to
+ * appropriate state. Note: this is not the same as
+ * voltage rampdown time, instead, consider the
+ * PMIC to have switched it's LDOs down, this is
+ * time taken to reach it's lowest power state(say
+ * sleep/OFF).
+ * @pmic_lp_tstart: Time rounded up to uSec for the PMIC to
+ * provide be ready for operation from low power
+ * state. Note: this is not the same as voltage
+ * rampup time, instead, consider the PMIC to be
+ * in lowest power state(say OFF), this is the time
+ * required for it to become ready for it's DCDCs
+ * or LDOs to start operation.
+ */
+struct omap_pmic_description {
+ u32 pmic_lp_tshut;
+ u32 pmic_lp_tstart;
+};
+
+#ifdef CONFIG_PM
+extern int omap_pmic_register_data(struct omap_pmic_map *map,
+ struct omap_pmic_description *desc);
+#else
+static inline int omap_pmic_register_data(struct omap_pmic_map *map,
+ struct omap_pmic_description *desc)
+{
+ return -EINVAL;
+}
+#endif
+extern void omap_pmic_data_init(void);
+
+extern int omap_pmic_update(struct omap_pmic_map *tmp_map, char *name,
+ u32 old_chip_id, u32 new_chip_id);
+
#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);
+extern int omap_twl_pmic_update(char *name, u32 old_chip_id, u32 new_chip_id);
#else
-static inline int omap3_twl_init(void)
+static inline int omap_twl_init(void)
{
return -EINVAL;
}
-static inline int omap4_twl_init(void)
+static inline int omap_twl_pmic_update(char *name, u32 old_chip_id,
+ u32 new_chip_id)
{
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);
+
+extern int omap_tps6236x_update(char *name, u32 old_chip_id, u32 new_chip_id);
+#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 omap_tps6236x_init(void)
+{
+ return -EINVAL;
+}
+static inline int omap_tps6236x_update(char *name, u32 old_chip_id,
+ u32 new_chip_id)
+{
+ return -EINVAL;
+}
+#endif
+
+extern int omap4_ldo_trim_configure(void);
+
+#ifdef CONFIG_PM
+extern bool omap_pm_is_ready_status;
+/**
+ * omap_pm_is_ready() - tells if OMAP pm framework is done it's initialization
+ *
+ * In few cases, to sequence operations properly, we'd like to know if OMAP's PM
+ * framework has completed all it's expected initializations.
+ */
+static inline bool omap_pm_is_ready(void)
+{
+ return omap_pm_is_ready_status;
+}
+extern int omap_pm_get_osc_lp_time(u32 *tstart, u32 *tshut);
+extern int omap_pm_get_pmic_lp_time(u32 *tstart, u32 *tshut);
+extern void omap_pm_set_osc_lp_time(u32 tstart, u32 tshut);
+extern void omap_pm_set_pmic_lp_time(u32 tstart, u32 tshut);
+#else
+static inline bool omap_pm_is_ready(void)
+{
+ return false;
+}
+static inline int omap_pm_get_osc_lp_time(u32 *tstart, u32 *tshut)
+{
+ return -EINVAL;
+}
+static inline int omap_pm_get_pmic_lp_time(u32 *tstart, u32 *tshut)
+{
+ return -EINVAL;
+}
+static inline void omap_pm_set_osc_lp_time(u32 tstart, u32 tshut) { }
+static inline void omap_pm_set_pmic_lp_time(u32 tstart, u32 tshut) { }
+#endif
#endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index df3ded6..faa8463 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -132,26 +132,12 @@ static void omap2_enter_full_retention(void)
if (omap_irq_pending())
goto no_sleep;
- /* Block console output in case it is on one of the OMAP UARTs */
- if (!is_suspending())
- if (!console_trylock())
- goto no_sleep;
-
- omap_uart_prepare_idle(0);
- omap_uart_prepare_idle(1);
- omap_uart_prepare_idle(2);
-
/* Jump to SRAM suspend code */
omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
OMAP_SDRC_REGADDR(SDRC_POWER));
- omap_uart_resume_idle(2);
- omap_uart_resume_idle(1);
- omap_uart_resume_idle(0);
-
- if (!is_suspending())
- console_unlock();
+ omap_uart_resume_idle();
no_sleep:
if (omap2_pm_debug) {
@@ -162,7 +148,7 @@ no_sleep:
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
omap2_pm_dump(0, 1, tmp);
}
- omap2_gpio_resume_after_idle();
+ omap2_gpio_resume_after_idle(0);
clk_enable(osc_ck);
@@ -267,8 +253,6 @@ static int omap2_can_sleep(void)
{
if (omap2_fclks_active())
return 0;
- if (!omap_uart_can_sleep())
- return 0;
if (osc_ck->usecount > 1)
return 0;
if (omap_dma_running())
@@ -319,7 +303,6 @@ static int omap2_pm_suspend(void)
mir1 = omap_readl(0x480fe0a4);
omap_writel(1 << 5, 0x480fe0ac);
- omap_uart_prepare_suspend();
omap2_enter_full_retention();
omap_writel(mir1, 0x480fe0a4);
@@ -518,6 +501,8 @@ static int __init omap2_pm_init(void)
suspend_set_ops(&omap_pm_ops);
pm_idle = omap2_pm_idle;
+ omap_pm_is_ready_status = true;
+
return 0;
}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c155c9d..cb1e8d8 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -91,16 +91,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
static struct powerdomain *cam_pwrdm;
-static inline void omap3_per_save_context(void)
-{
- omap_gpio_save_context();
-}
-
-static inline void omap3_per_restore_context(void)
-{
- omap_gpio_restore_context();
-}
-
static void omap3_enable_io_chain(void)
{
int timeout = 0;
@@ -146,7 +136,7 @@ static void omap3_core_save_context(void)
/* Save the Interrupt controller context */
omap_intc_save_context();
/* Save the GPMC context */
- omap3_gpmc_save_context();
+ omap_gpmc_save_context();
/* Save the system control module context, padconf already save above*/
omap3_control_save_context();
omap_dma_global_context_save();
@@ -157,7 +147,7 @@ static void omap3_core_restore_context(void)
/* Restore the control module context, padconf restored by h/w */
omap3_control_restore_context();
/* Restore the GPMC context */
- omap3_gpmc_restore_context();
+ omap_gpmc_restore_context();
/* Restore the interrupt controller context */
omap_intc_restore_context();
omap_dma_global_context_restore();
@@ -216,6 +206,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
wkst = omap2_prm_read_mod_reg(module, wkst_off);
wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
+
+ c += omap_uart_resume_idle();
if (wkst) {
iclk = omap2_cm_read_mod_reg(module, iclk_off);
fclk = omap2_cm_read_mod_reg(module, fclk_off);
@@ -336,7 +328,7 @@ static void restore_table_entry(void)
set_cr(control_reg_value);
}
-void omap_sram_idle(void)
+void omap_sram_idle(bool suspend)
{
/* Variable to tell what needs to be saved and restored
* in omap_sram_idle*/
@@ -375,7 +367,6 @@ void omap_sram_idle(void)
printk(KERN_ERR "Invalid mpu state in sram_idle\n");
return;
}
- pwrdm_pre_transition();
/* NEON control */
if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
@@ -391,27 +382,15 @@ void omap_sram_idle(void)
omap3_enable_io_chain();
}
- /* Block console output in case it is on one of the OMAP UARTs */
- if (!is_suspending())
- if (per_next_state < PWRDM_POWER_ON ||
- core_next_state < PWRDM_POWER_ON)
- if (!console_trylock())
- goto console_still_active;
-
+ pwrdm_pre_transition();
/* PER */
if (per_next_state < PWRDM_POWER_ON) {
per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
- omap_uart_prepare_idle(2);
- omap_uart_prepare_idle(3);
- omap2_gpio_prepare_for_idle(per_going_off);
- if (per_next_state == PWRDM_POWER_OFF)
- omap3_per_save_context();
+ omap2_gpio_prepare_for_idle(per_going_off, suspend);
}
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
- omap_uart_prepare_idle(0);
- omap_uart_prepare_idle(1);
if (core_next_state == PWRDM_POWER_OFF) {
omap3_core_save_context();
omap3_cm_save_context();
@@ -458,8 +437,6 @@ void omap_sram_idle(void)
omap3_sram_restore_context();
omap2_sms_restore_context();
}
- omap_uart_resume_idle(0);
- omap_uart_resume_idle(1);
if (core_next_state == PWRDM_POWER_OFF)
omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
OMAP3430_GR_MOD,
@@ -467,20 +444,14 @@ void omap_sram_idle(void)
}
omap3_intc_resume_idle();
+ pwrdm_post_transition();
+
/* PER */
if (per_next_state < PWRDM_POWER_ON) {
per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
- omap2_gpio_resume_after_idle();
- if (per_prev_state == PWRDM_POWER_OFF)
- omap3_per_restore_context();
- omap_uart_resume_idle(2);
- omap_uart_resume_idle(3);
+ omap2_gpio_resume_after_idle(per_going_off);
}
- if (!is_suspending())
- console_unlock();
-
-console_still_active:
/* Disable IO-PAD and IO-CHAIN wakeup */
if (omap3_has_io_wakeup() &&
(per_next_state < PWRDM_POWER_ON ||
@@ -490,8 +461,6 @@ console_still_active:
omap3_disable_io_chain();
}
- pwrdm_post_transition();
-
clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
}
@@ -499,8 +468,6 @@ int omap3_can_sleep(void)
{
if (!sleep_while_idle)
return 0;
- if (!omap_uart_can_sleep())
- return 0;
return 1;
}
@@ -518,7 +485,7 @@ static void omap3_pm_idle(void)
trace_power_start(POWER_CSTATE, 1, smp_processor_id());
trace_cpu_idle(1, smp_processor_id());
- omap_sram_idle();
+ omap_sram_idle(false);
trace_power_end(smp_processor_id());
trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
@@ -549,10 +516,9 @@ static int omap3_pm_suspend(void)
goto restore;
}
- omap_uart_prepare_suspend();
omap3_intc_suspend();
- omap_sram_idle();
+ omap_sram_idle(true);
restore:
/* Restore next_pwrsts */
@@ -596,14 +562,12 @@ static int omap3_pm_begin(suspend_state_t state)
{
disable_hlt();
suspend_state = state;
- omap_uart_enable_irqs(0);
return 0;
}
static void omap3_pm_end(void)
{
suspend_state = PM_SUSPEND_ON;
- omap_uart_enable_irqs(1);
enable_hlt();
return;
}
@@ -956,6 +920,7 @@ static int __init omap3_pm_init(void)
}
omap3_save_scratchpad_contents();
+ omap_pm_is_ready_status = true;
err1:
return ret;
err2:
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 59a870b..b9e2bf1 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,28 +13,713 @@
#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 <linux/irq.h>
-#include "powerdomain.h"
+#include <asm/hardware/gic.h>
#include <mach/omap4-common.h>
+#include <plat/omap_hsi.h>
+#include <plat/common.h>
+#include <plat/temperature_sensor.h>
+#include <plat/usb.h>
+#include <plat/prcm.h>
+#include <plat/omap-pm.h>
+#include <plat/gpmc.h>
+#include <plat/dma.h>
+
+#include <mach/omap_fiq_debugger.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 "cm44xx.h"
+#include "cm-regbits-44xx.h"
+#include "cminst44xx.h"
+#include "scrm44xx.h"
+#include "prcm-debug.h"
+
+#include "smartreflex.h"
+#include "dvfs.h"
+#include "voltage.h"
+#include "vc.h"
+#include "control.h"
struct power_state {
struct powerdomain *pwrdm;
u32 next_state;
#ifdef CONFIG_SUSPEND
u32 saved_state;
+ u32 saved_logic_state;
#endif
struct list_head node;
};
static LIST_HEAD(pwrst_list);
+static struct powerdomain *mpu_pwrdm, *cpu0_pwrdm;
+static struct powerdomain *core_pwrdm, *per_pwrdm;
+
+static struct voltagedomain *mpu_voltdm, *iva_voltdm, *core_voltdm;
+
+static struct clockdomain *tesla_clkdm;
+static struct powerdomain *tesla_pwrdm;
+
+static struct clockdomain *emif_clkdm, *mpuss_clkdm;
+
+/* Yet un-named erratum which requires AUTORET to be disabled for IVA PD */
+#define OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX BIT(1)
+
+/* Dynamic dependendency Cannot be enabled due to i688 erratum ID for 443x */
+#define OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_i688 BIT(3)
+/*
+ * Dynamic dependendency Cannot be enabled due to i688 erratum ID for above 443x
+ * NOTE: this is NOT YET a confirmed erratum for 446x, but provided here in
+ * anticipation.
+ * If a fix is found at a later date, the code using this can be removed.
+ * WA involves:
+ * Enable MPU->EMIF SD before WFI and disable while coming out of WFI.
+ * This works around system hang/lockups seen when only MPU->EMIF
+ * dynamic dependency set. Allows dynamic dependency to be used
+ * in all active usecases and get all the power savings accordingly.
+ * TODO: Once this is available as final Errata, update with proper
+ * fix.
+ */
+#define OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_IDLE_iXXX BIT(4)
+
+static u8 pm44xx_errata;
+#define is_pm44xx_erratum(erratum) (pm44xx_errata & OMAP4_PM_ERRATUM_##erratum)
+
+#define MAX_IOPAD_LATCH_TIME 1000
+void omap4_trigger_ioctrl(void)
+{
+ int i = 0;
+
+ /* Enable GLOBAL_WUEN */
+ if (!omap4_cminst_read_inst_reg_bits(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET,
+ OMAP4430_GLOBAL_WUEN_MASK))
+ 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);
+
+ /* 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_MASK) >>
+ OMAP4430_WUCLK_STATUS_SHIFT) == 1),
+ MAX_IOPAD_LATCH_TIME, i);
+ if (i == MAX_IOPAD_LATCH_TIME)
+ pr_err("%s: Max IO latch time reached for WUCLKIN enable\n",
+ __func__);
+
+ /* 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);
+
+ /* Ensure this is cleared */
+ omap_test_timeout((((omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_IO_PMCTRL_OFFSET) &
+ OMAP4430_WUCLK_STATUS_MASK) >>
+ OMAP4430_WUCLK_STATUS_SHIFT) == 0),
+ MAX_IOPAD_LATCH_TIME, i);
+ if (i == MAX_IOPAD_LATCH_TIME)
+ pr_err("%s: Max IO latch time reached for WUCLKIN disable\n",
+ __func__);
+ 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, bool suspend)
+{
+ int cpu0_next_state = PWRDM_POWER_ON;
+ int per_next_state = PWRDM_POWER_ON;
+ int core_next_state = PWRDM_POWER_ON;
+ int mpu_next_state = PWRDM_POWER_ON;
+ int ret;
+ int staticdep_wa_applied = 0;
+
+ 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);
+ omap4_device_clear_prev_off_state();
+
+ /*
+ * Just return if we detect a scenario where we conflict
+ * with DVFS
+ */
+ if (omap_dvfs_is_any_dev_scaling())
+ return;
+
+ 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);
+ mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+
+ ret = omap2_gpio_prepare_for_idle(omap4_device_next_state_off(), suspend);
+ if (ret)
+ goto abort_gpio;
+
+ if (is_pm44xx_erratum(MPU_EMIF_NO_DYNDEP_IDLE_iXXX) &&
+ mpu_next_state <= PWRDM_POWER_INACTIVE) {
+ /* Configures MEMIF clockdomain in SW_WKUP */
+ if (clkdm_wakeup(emif_clkdm)) {
+ pr_err("%s: Failed to force wakeup of %s\n",
+ __func__, emif_clkdm->name);
+ } else {
+ /* Enable MPU-EMIF Static Dependency around WFI */
+ if (clkdm_add_wkdep(mpuss_clkdm, emif_clkdm))
+ pr_err("%s: Failed to Add wkdep %s->%s\n",
+ __func__, mpuss_clkdm->name,
+ emif_clkdm->name);
+ else
+ staticdep_wa_applied = 1;
+
+ /* Configures MEMIF clockdomain back to HW_AUTO */
+ clkdm_allow_idle(emif_clkdm);
+ }
+ }
+ if (mpu_next_state < PWRDM_POWER_INACTIVE) {
+ if (omap_sr_disable_reset_volt(mpu_voltdm))
+ goto abort_device_off;
+
+ omap_sr_disable_reset_volt(mpu_voltdm);
+ omap_vc_set_auto_trans(mpu_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION);
+ }
+
+ if (core_next_state < PWRDM_POWER_ON) {
+ /*
+ * Note: IVA can hit RET outside of cpuidle and hence this is
+ * not the right optimal place to enable IVA AUTO RET. But since
+ * enabling AUTO RET requires SR to disabled, its done here for
+ * now. Needs a relook to see if this can be optimized.
+ */
+ if (omap_sr_disable_reset_volt(iva_voltdm))
+ goto abort_device_off;
+ if (omap_sr_disable_reset_volt(core_voltdm))
+ goto abort_device_off;
+ omap_vc_set_auto_trans(core_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION);
+ if (!is_pm44xx_erratum(IVA_AUTO_RET_iXXX)) {
+ omap_vc_set_auto_trans(iva_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION);
+ }
+
+ omap_temp_sensor_prepare_idle();
+ }
+
+ if (omap4_device_next_state_off()) {
+ omap_gpmc_save_context();
+ omap_dma_global_context_save();
+ }
+
+ if (suspend && cpu_is_omap44xx())
+ omap4_pm_suspend_save_regs();
+
+ if (omap4_device_next_state_off()) {
+ /* Save the device context to SAR RAM */
+ if (omap4_sar_save())
+ goto abort_device_off;
+ omap4_sar_overwrite();
+ omap4_cm_prepare_off();
+ omap4_dpll_prepare_off();
+
+ /* Extend Non-EMIF I/O isolation */
+ omap4_prminst_rmw_inst_reg_bits(OMAP4430_ISOOVR_EXTEND_MASK,
+ OMAP4430_ISOOVR_EXTEND_MASK, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET);
+ }
+
+ omap4_enter_lowpower(cpu, power_state);
+
+ if (omap4_device_prev_state_off()) {
+ /* Reconfigure the trim settings as well */
+ omap4_ldo_trim_configure();
+ omap4_dpll_resume_off();
+ omap4_cm_resume_off();
+#ifdef CONFIG_PM_DEBUG
+ omap4_device_off_counter++;
+#endif
+ }
+
+abort_device_off:
+ if (core_next_state < PWRDM_POWER_ON) {
+ /* See note above */
+ omap_vc_set_auto_trans(core_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
+ if (!is_pm44xx_erratum(IVA_AUTO_RET_iXXX)) {
+ omap_vc_set_auto_trans(iva_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
+ }
+
+ omap_temp_sensor_resume_idle();
+ omap_sr_enable(iva_voltdm,
+ omap_voltage_get_curr_vdata(iva_voltdm));
+ omap_sr_enable(core_voltdm,
+ omap_voltage_get_curr_vdata(core_voltdm));
+ }
+
+ if (omap4_device_prev_state_off()) {
+ omap_dma_global_context_restore();
+ omap_gpmc_restore_context();
+ }
+
+ omap2_gpio_resume_after_idle(omap4_device_next_state_off());
+
+ if (omap4_device_next_state_off()) {
+ /* Disable the extension of Non-EMIF I/O isolation */
+ omap4_prminst_rmw_inst_reg_bits(OMAP4430_ISOOVR_EXTEND_MASK,
+ 0, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET);
+ }
+
+ if (mpu_next_state < PWRDM_POWER_INACTIVE) {
+ omap_vc_set_auto_trans(mpu_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
+ omap_sr_enable(mpu_voltdm,
+ omap_voltage_get_curr_vdata(mpu_voltdm));
+ }
+
+ /*
+ * NOTE: is_pm44xx_erratum is not strictly required, but retained for
+ * code context redability.
+ */
+ if (is_pm44xx_erratum(MPU_EMIF_NO_DYNDEP_IDLE_iXXX) &&
+ staticdep_wa_applied) {
+ /* Configures MEMIF clockdomain in SW_WKUP */
+ if (clkdm_wakeup(emif_clkdm))
+ pr_err("%s: Failed to force wakeup of %s\n",
+ __func__, emif_clkdm->name);
+ /* Disable MPU-EMIF Static Dependency on WFI exit */
+ else if (clkdm_del_wkdep(mpuss_clkdm, emif_clkdm))
+ pr_err("%s: Failed to remove wkdep %s->%s\n",
+ __func__, mpuss_clkdm->name,
+ emif_clkdm->name);
+ /* Configures MEMIF clockdomain back to HW_AUTO */
+ clkdm_allow_idle(emif_clkdm);
+ }
+
+abort_gpio:
+ return;
+}
+
+#ifdef CONFIG_PM_DEBUG
+#define GPIO_BANKS 6
+#define MODULEMODE_DISABLED 0x0
+#define MODULEMODE_AUTO 0x1
+
+static void _print_wakeirq(int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ if (irq == OMAP44XX_IRQ_LOCALTIMER)
+ pr_info("Resume caused by IRQ %d, localtimer\n", irq);
+ else if (!desc || !desc->action || !desc->action->name)
+ pr_info("Resume caused by IRQ %d\n", irq);
+ else
+ pr_info("Resume caused by IRQ %d, %s\n", irq,
+ desc->action->name);
+}
+
+static void _print_gpio_wakeirq(int irq)
+{
+ int bank = irq - OMAP44XX_IRQ_GPIO1;
+ int bit;
+ int gpioirq;
+ int restoremod = 0;
+ int timeout = 10;
+ u32 wken, irqst, gpio;
+ u32 clkctrl;
+ long unsigned int wkirqs;
+ void *gpio_base[GPIO_BANKS] = {
+ OMAP2_L4_IO_ADDRESS(0x4a310000),
+ OMAP2_L4_IO_ADDRESS(0x48055000),
+ OMAP2_L4_IO_ADDRESS(0x48057000),
+ OMAP2_L4_IO_ADDRESS(0x48059000),
+ OMAP2_L4_IO_ADDRESS(0x4805b000),
+ OMAP2_L4_IO_ADDRESS(0x4805d000),
+ };
+ void *gpio_clkctrl[GPIO_BANKS] = {
+ OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+ OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+ OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+ OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+ OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+ OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+ };
+
+ /*
+ * GPIO1 is in CD_WKUP.
+ * GPIO2-6 are in CD_l4_PER.
+ *
+ * Both of these clock domains are static dependencies of
+ * the MPUSS clock domain (CD_CORTEXA9) and are guaranteed
+ * to be already enabled (_CLKSTCTRL.CLKTRCTRL = HW_AUTO).
+ *
+ * Ensure the GPIO module is enabled (_CLKCTRL.MODULEMODE =
+ * h/w managed). If not, will set it back to disabled when
+ * done.
+ */
+
+ clkctrl = __raw_readl(gpio_clkctrl[bank]);
+
+ if ((clkctrl & OMAP4430_MODULEMODE_MASK) !=
+ MODULEMODE_AUTO << OMAP4430_MODULEMODE_SHIFT) {
+ restoremod = 1;
+ __raw_writel((clkctrl & ~(OMAP4430_MODULEMODE_MASK)) |
+ MODULEMODE_AUTO << OMAP4430_MODULEMODE_SHIFT,
+ gpio_clkctrl[bank]);
+
+ while ((__raw_readl(gpio_clkctrl[bank]) &
+ OMAP4430_MODULEMODE_MASK) !=
+ MODULEMODE_AUTO << OMAP4430_MODULEMODE_SHIFT &&
+ --timeout)
+ udelay(5);
+
+ if (!timeout)
+ goto punt;
+ }
+
+ wken = __raw_readl(gpio_base[bank] + OMAP4_GPIO_IRQWAKEN0);
+ irqst = __raw_readl(gpio_base[bank] + OMAP4_GPIO_IRQSTATUS0);
+ wkirqs = irqst & wken;
+
+ if (!wkirqs)
+ wkirqs = irqst;
+
+ if (!wkirqs)
+ goto punt;
+
+ for_each_set_bit(bit, &wkirqs, 32) {
+ gpio = bit + bank * 32;
+ gpioirq = gpio_to_irq(gpio);
+
+ if (gpioirq < 0)
+ pr_info("Resume caused by GPIO %d\n", (int)gpio);
+ else
+ _print_wakeirq(gpioirq);
+ }
+
+ goto out;
+
+punt:
+ pr_info("Resume caused by IRQ %d, unknown GPIO%d interrupt\n", irq,
+ bank + 1);
+
+out:
+ if (restoremod)
+ __raw_writel(clkctrl, gpio_clkctrl[bank]);
+}
+
+#define CONTROL_PADCONF_WAKEUPEVENT_0 0x4a1001d8
+#define CONTROL_WKUP_PADCONF_WAKEUPEVENT_0 0x4a31E07C
+
+static void _print_prcm_wakeirq(int irq)
+{
+ int i, bit;
+ int iopad_wake_found = 0;
+ u32 prcm_irqs1, prcm_irqs2;
+ long unsigned int wkup_pad_event;
+
+ prcm_irqs1 = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+ OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
+ prcm_irqs1 &= omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+ OMAP4_PRM_IRQENABLE_MPU_OFFSET);
+ prcm_irqs2 = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+ OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
+ prcm_irqs2 &= omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+ OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
+
+ if (prcm_irqs1 & OMAP4430_IO_ST_MASK) {
+ for (i = 0; i <= 6; i++) {
+ long unsigned int wkevt =
+ omap_readl(CONTROL_PADCONF_WAKEUPEVENT_0 + i*4);
+
+ for_each_set_bit(bit, &wkevt, 32) {
+ pr_info("Resume caused by I/O pad: CONTROL_PADCONF_WAKEUPEVENT_%d[%d]\n",
+ i, bit);
+ iopad_wake_found = 1;
+ }
+ }
+ wkup_pad_event = omap_readl(CONTROL_WKUP_PADCONF_WAKEUPEVENT_0);
+ for_each_set_bit(bit, &wkup_pad_event, 25) {
+ pr_info("Resume caused by wakeup I/O pad: CONTROL_WKUP_PADCONF_WAKEUPEVENT_0[%d]\n", bit);
+ iopad_wake_found = 1;
+ }
+ }
+
+ if (prcm_irqs1 & ~OMAP4430_IO_ST_MASK || !iopad_wake_found ||
+ prcm_irqs2)
+ pr_info("Resume caused by IRQ %d, prcm: 0x%x 0x%x\n", irq,
+ prcm_irqs1, prcm_irqs2);
+}
+
+static void omap4_print_wakeirq(void)
+{
+ int irq;
+
+ irq = gic_cpu_read(GIC_CPU_HIGHPRI) & 0x3ff;
+
+ if ((irq == 1022) || (irq == 1023)) {
+ pr_info("GIC returns spurious interrupt for resume IRQ\n");
+ return;
+ }
+
+ if (irq >= OMAP44XX_IRQ_GPIO1 &&
+ irq <= OMAP44XX_IRQ_GPIO1 + GPIO_BANKS - 1)
+ _print_gpio_wakeirq(irq);
+ else if (irq == OMAP44XX_IRQ_PRCM)
+ _print_prcm_wakeirq(irq);
+ else
+ _print_wakeirq(irq);
+}
+#else
+static void omap4_print_wakeirq(void)
+{
+}
+#endif
+
+/**
+ * get_achievable_state() - Provide achievable state
+ * @available_states: what states are available
+ * @req_min_state: what state is the minimum we'd like to hit
+ * @is_parent_pd: is this a parent power domain?
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain, in which case:
+ * a) if this power domain is a parent power domain, we do not intend
+ * for it to go to a lower power state(because we are not targetting it),
+ * select the next higher power state which is supported is returned.
+ * b) However, for all children power domains, we first try to match
+ * with a lower power domain state before attempting a higher state.
+ * This is because a combination of system power states where the
+ * parent PD's state is not in line with expectation can result in
+ * system instabilities.
+ */
+static inline u8 get_achievable_state(u8 available_states, u8 req_min_state,
+ bool is_parent_pd)
+{
+ u8 max_mask = 0xFF << req_min_state;
+ u8 min_mask = ~max_mask;
+
+ /* First see if we have an accurate match */
+ if (available_states & BIT(req_min_state))
+ return req_min_state;
+
+ /* See if a lower power state is possible on this child domain */
+ if (!is_parent_pd && available_states & min_mask)
+ return __ffs(available_states & min_mask);
+
+ if (available_states & max_mask)
+ return __ffs(available_states & max_mask);
+
+ return PWRDM_POWER_ON;
+}
+
+/**
+ * omap4_configure_pwdm_suspend() - Program powerdomain on suspend
+ * @is_off_mode: is this an OFF mode transition?
+ *
+ * Program all powerdomain to required power domain state: This logic
+ * Takes the requested mode -OFF/RET translates it to logic and power
+ * states. This then walks down the power domain states to program
+ * each domain to the state requested. if the requested state is not
+ * available, it will check for the higher state.
+ */
+static void omap4_configure_pwdm_suspend(bool is_off_mode)
+{
+ struct power_state *pwrst;
+ u32 state;
+ u32 logic_state, als;
+
+#ifdef CONFIG_OMAP_ALLOW_OSWR
+ if (is_off_mode) {
+ state = PWRDM_POWER_OFF;
+ logic_state = PWRDM_POWER_OFF;
+ } else {
+ state = PWRDM_POWER_RET;
+ logic_state = PWRDM_POWER_OFF;
+ }
+#else
+ state = PWRDM_POWER_RET;
+ logic_state = PWRDM_POWER_RET;
+#endif
+
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ bool parent_power_domain = false;
+
+ pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+ pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
+
+ if ((!strcmp(pwrst->pwrdm->name, "cpu0_pwrdm")) ||
+ (!strcmp(pwrst->pwrdm->name, "cpu1_pwrdm")))
+ continue;
+ if (!strcmp(pwrst->pwrdm->name, "core_pwrdm") ||
+ !strcmp(pwrst->pwrdm->name, "mpu_pwrdm") ||
+ !strcmp(pwrst->pwrdm->name, "iva_pwrdm"))
+ parent_power_domain = true;
+ /*
+ * Write only to registers which are writable! Don't touch
+ * read-only/reserved registers. If pwrdm->pwrsts_logic_ret or
+ * pwrdm->pwrsts are 0, consider those power domains containing
+ * readonly/reserved registers which cannot be controlled by
+ * software.
+ */
+ if (pwrst->pwrdm->pwrsts_logic_ret) {
+ als =
+ get_achievable_state(pwrst->pwrdm->pwrsts_logic_ret,
+ logic_state, parent_power_domain);
+ if (als < pwrst->saved_logic_state)
+ pwrdm_set_logic_retst(pwrst->pwrdm, als);
+ }
+ if (pwrst->pwrdm->pwrsts) {
+ pwrst->next_state =
+ get_achievable_state(pwrst->pwrdm->pwrsts, state,
+ parent_power_domain);
+ if (pwrst->next_state < pwrst->saved_state)
+ omap_set_pwrdm_state(pwrst->pwrdm,
+ pwrst->next_state);
+ else
+ pwrst->next_state = pwrst->saved_state;
+ }
+ }
+}
+
+/**
+ * omap4_restore_pwdms_after_suspend() - Restore powerdomains after suspend
+ *
+ * Re-program all powerdomains to saved power domain states.
+ *
+ * returns 0 if all power domains hit targeted power state, -1 if any domain
+ * failed to hit targeted power state (status related to the actual restore
+ * is not returned).
+ */
+static int omap4_restore_pwdms_after_suspend(void)
+{
+ struct power_state *pwrst;
+ int cstate, pstate, ret = 0;
+
+ /* Restore next powerdomain state */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ cstate = pwrdm_read_pwrst(pwrst->pwrdm);
+ pstate = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+ if (pstate > pwrst->next_state) {
+ pr_info("Powerdomain (%s) didn't enter "
+ "target state %d Vs achieved state %d. "
+ "current state %d\n",
+ pwrst->pwrdm->name, pwrst->next_state,
+ pstate, cstate);
+ ret = -1;
+ }
+
+ /* If state already ON due to h/w dep, don't do anything */
+ if (cstate == PWRDM_POWER_ON)
+ continue;
+
+ /* If we have already achieved saved state, nothing to do */
+ if (cstate == pwrst->saved_state)
+ continue;
+
+ /* mpuss code takes care of this */
+ if ((!strcmp(pwrst->pwrdm->name, "cpu0_pwrdm")) ||
+ (!strcmp(pwrst->pwrdm->name, "cpu1_pwrdm")))
+ continue;
+
+ /*
+ * Skip pd program if saved state higher than current state
+ * Since we would have already returned if the state
+ * was ON, if the current state is yet another low power
+ * state, the PRCM specification clearly states that
+ * transition from a lower LP state to a higher LP state
+ * is forbidden.
+ */
+ if (pwrst->saved_state > cstate)
+ continue;
+
+ if (pwrst->pwrdm->pwrsts)
+ omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+
+ if (pwrst->pwrdm->pwrsts_logic_ret)
+ pwrdm_set_logic_retst(pwrst->pwrdm,
+ pwrst->saved_logic_state);
+ }
+
+ return ret;
+}
+
static int omap4_pm_suspend(void)
{
- do_wfi();
+ int ret = 0;
+
+ /*
+ * If any device was in the middle of a scale operation
+ * then abort, as we cannot predict which part of the scale
+ * operation we interrupted.
+ */
+ if (omap_dvfs_is_any_dev_scaling()) {
+ pr_err("%s: oops.. middle of scale op.. aborting suspend\n",
+ __func__);
+ return -EBUSY;
+ }
+
+ /* Wakeup timer from suspend */
+ if (wakeup_timer_seconds || wakeup_timer_milliseconds)
+ omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
+ wakeup_timer_milliseconds);
+
+ omap4_configure_pwdm_suspend(off_mode_enabled);
+
+ /* Enable Device OFF */
+ if (off_mode_enabled)
+ omap4_device_set_state_off(1);
+
+ /*
+ * 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.
+ */
+ omap4_enter_sleep(0, PWRDM_POWER_OFF, true);
+ omap4_print_wakeirq();
+ prcmdebug_dump(PRCMDEBUG_LASTSLEEP);
+
+ /* Disable Device OFF state*/
+ if (off_mode_enabled)
+ omap4_device_set_state_off(0);
+
+ ret = omap4_restore_pwdms_after_suspend();
+
+ 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 +757,55 @@ 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 */
+/**
+ * omap4_pm_cold_reset() - Cold reset OMAP4
+ * @reason: why am I resetting.
+ *
+ * As per the TRM, it is recommended that we set all the power domains to
+ * ON state before we trigger cold reset.
+ */
+int omap4_pm_cold_reset(char *reason)
+{
+ struct power_state *pwrst;
+
+ /* Switch ON all pwrst registers */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ if (pwrst->pwrdm->pwrsts_logic_ret)
+ pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_ON);
+ if (pwrst->pwrdm->pwrsts)
+ omap_set_pwrdm_state(pwrst->pwrdm, PWRDM_POWER_ON);
+ }
+
+ WARN(1, "Arch Cold reset has been triggered due to %s\n", reason);
+ omap4_prm_global_cold_sw_reset(); /* never returns */
+
+ /* If we reached here - something bad went on.. */
+ BUG();
+
+ /* make the compiler happy */
+ return -EINTR;
+}
+
+/*
+ * 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 +816,397 @@ 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 int __init _voltdm_sum_time(struct voltagedomain *voltdm, void *user)
+{
+ struct omap_voltdm_pmic *pmic;
+ u32 *max_time = (u32 *)user;
+
+ if (!voltdm || !max_time) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ pmic = voltdm->pmic;
+ if (pmic) {
+ *max_time += pmic->on_volt / pmic->slew_rate;
+ *max_time += pmic->switch_on_time;
+ }
+
+ return 0;
+}
+
+static u32 __init _usec_to_val_scrm(unsigned long rate, u32 usec,
+ u32 shift, u32 mask)
+{
+ u32 val;
+
+ /* limit to max value */
+ val = ((mask >> shift) * 1000000) / rate;
+ if (usec > val)
+ usec = val;
+
+ /* convert the time in usec to cycles */
+ val = DIV_ROUND_UP(rate * usec, 1000000);
+ return (val << shift) & mask;
+
+}
+
+static void __init syscontrol_setup_regs(void)
+{
+ u32 v;
+
+ /* Disable LPDDR VREF manual control and enable Auto control */
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3);
+ v &= ~(OMAP4_LPDDR21_VREF_EN_CA_MASK | OMAP4_LPDDR21_VREF_EN_DQ_MASK);
+ v |= OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK | OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK;
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3);
+
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3);
+ v &= ~(OMAP4_LPDDR21_VREF_EN_CA_MASK | OMAP4_LPDDR21_VREF_EN_DQ_MASK);
+ v |= OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK | OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK;
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3);
+
+ /*
+ * Workaround for CK differential IO PADn, PADp values due to bug in
+ * EMIF CMD phy.
+ */
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2);
+ v &= ~OMAP4_LPDDR2IO1_GR10_WD_MASK;
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2);
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2);
+ v &= ~OMAP4_LPDDR2IO2_GR10_WD_MASK;
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2);
+}
+
+static void __init prcm_setup_regs(void)
+{
+ struct clk *clk32k = clk_get(NULL, "sys_32k_ck");
+ unsigned long rate32k = 0;
+ u32 val, tshut, tstart;
+ u32 reset_delay_time = 0;
+
+ if (clk32k) {
+ rate32k = clk_get_rate(clk32k);
+ clk_put(clk32k);
+ } else {
+ pr_err("%s: no 32k clk!!!\n", __func__);
+ dump_stack();
+ }
+
+ /* 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);
+
+ /*
+ * 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);
+
+ /* Allow SRAM LDO to enter RET during low power state*/
+ if (cpu_is_omap446x()) {
+ omap4_prminst_rmw_inst_reg_bits(OMAP4430_RETMODE_ENABLE_MASK,
+ 0x1 << OMAP4430_RETMODE_ENABLE_SHIFT, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_LDO_SRAM_CORE_CTRL_OFFSET);
+ omap4_prminst_rmw_inst_reg_bits(OMAP4430_RETMODE_ENABLE_MASK,
+ 0x1 << OMAP4430_RETMODE_ENABLE_SHIFT, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_LDO_SRAM_MPU_CTRL_OFFSET);
+ omap4_prminst_rmw_inst_reg_bits(OMAP4430_RETMODE_ENABLE_MASK,
+ 0x1 << OMAP4430_RETMODE_ENABLE_SHIFT, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_LDO_SRAM_IVA_CTRL_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);
+
+ if (!rate32k)
+ goto no_32k;
+
+ /* Setup max clksetup time for oscillator */
+ omap_pm_get_osc_lp_time(&tstart, &tshut);
+ val = _usec_to_val_scrm(rate32k, tstart, OMAP4_SETUPTIME_SHIFT,
+ OMAP4_SETUPTIME_MASK);
+ val |= _usec_to_val_scrm(rate32k, tshut, OMAP4_DOWNTIME_SHIFT,
+ OMAP4_DOWNTIME_MASK);
+ omap4_prminst_write_inst_reg(val, OMAP4430_SCRM_PARTITION, 0x0,
+ OMAP4_SCRM_CLKSETUPTIME_OFFSET);
+
+ /*
+ * Setup OMAP WARMRESET time:
+ * we use the sum of each voltage domain setup times to handle
+ * the worst case condition where the device resets from OFF mode.
+ * hence we leave PRM_VOLTSETUP_WARMRESET alone as this is
+ * already part of RSTTIME1 we program in.
+ * in addition, to handle oscillator switch off and switch back on
+ * (in case WDT triggered while CLKREQ goes low), we also
+ * add in the additional latencies.
+ */
+ if (!voltdm_for_each(_voltdm_sum_time, (void *)&reset_delay_time)) {
+ reset_delay_time += tstart + tshut;
+ val = _usec_to_val_scrm(rate32k, reset_delay_time,
+ OMAP4430_RSTTIME1_SHIFT, OMAP4430_RSTTIME1_MASK);
+ omap4_prminst_rmw_inst_reg_bits(OMAP4430_RSTTIME1_MASK, val,
+ OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_RSTTIME_OFFSET);
+ }
+
+ /* Setup max PMIC startup time */
+ omap_pm_get_pmic_lp_time(&tstart, &tshut);
+ val = _usec_to_val_scrm(rate32k, tstart, OMAP4_WAKEUPTIME_SHIFT,
+ OMAP4_WAKEUPTIME_MASK);
+ val |= _usec_to_val_scrm(rate32k, tshut, OMAP4_SLEEPTIME_SHIFT,
+ OMAP4_SLEEPTIME_MASK);
+ omap4_prminst_write_inst_reg(val, OMAP4430_SCRM_PARTITION, 0x0,
+ OMAP4_SCRM_PMICSETUPTIME_OFFSET);
+
+no_32k:
+ /*
+ * 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);
+
+}
+
+
+/* omap_pm_clear_dsp_wake_up - SW WA for hardcoded wakeup dependency
+* from HSI to DSP
+*
+* Due to HW bug, same SWakeup signal is used for both MPU and DSP.
+* Thus Swakeup will unexpectedly wakeup the DSP domain even if nothing runs on
+* DSP. Since MPU is faster to process SWakeup, it acknowledges the Swakeup to
+* HSI before the DSP has completed its domain transition. This leaves the DSP
+* Power Domain in INTRANSITION state forever, and prevents the DEVICE-OFF mode.
+*
+* Workaround consists in :
+* when a SWakeup is asserted from HSI to MPU (and DSP) :
+* - force a DSP SW wakeup
+* - wait DSP module to be fully ON
+* - Configure a DSP CLK CTRL to HW_AUTO
+* - Wait on DSP module to be OFF
+*
+* Note : we detect a Swakeup is asserted to MPU by checking when an interrupt
+* is received while HSI module is ON.
+*
+* Bug ref is HSI-C1BUG00106 : dsp swakeup generated by HSI same as mpu swakeup
+*/
+static void omap_pm_clear_dsp_wake_up(void)
+{
+ int ret;
+ int timeout = 10;
+
+ if (!tesla_pwrdm || !tesla_clkdm) {
+ WARN_ONCE(1, "%s: unable to use tesla workaround\n", __func__);
+ return;
+ }
+
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ /*
+ * If current Tesla power state is in RET/OFF and not in transition,
+ * then not hit by errata.
+ */
+ if (ret <= PWRDM_POWER_RET) {
+ if (!(omap4_prminst_read_inst_reg(tesla_pwrdm->prcm_partition,
+ tesla_pwrdm->prcm_offs, OMAP4_PM_PWSTST)
+ & OMAP_INTRANSITION_MASK))
+ return;
+ }
+
+ if (clkdm_wakeup(tesla_clkdm))
+ pr_err("%s: Failed to force wakeup of %s\n", __func__,
+ tesla_clkdm->name);
+
+ /* This takes less than a few microseconds, hence in context */
+ pwrdm_wait_transition(tesla_pwrdm);
+
+ /*
+ * Check current power state of Tesla after transition, to make sure
+ * that Tesla is indeed turned ON.
+ */
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ do {
+ pwrdm_wait_transition(tesla_pwrdm);
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ } while ((ret < PWRDM_POWER_INACTIVE) && --timeout);
+
+ if (!timeout)
+ pr_err("%s: Tesla failed to transition to ON state!\n",
+ __func__);
+
+ timeout = 10;
+ clkdm_allow_idle(tesla_clkdm);
+
+ /* Ensure Tesla power state in OFF state */
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ do {
+ pwrdm_wait_transition(tesla_pwrdm);
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ } while ((ret >= PWRDM_POWER_INACTIVE) && --timeout);
+
+ if (!timeout)
+ pr_err("%s: Tesla failed to transition to OFF state\n",
+ __func__);
+
+}
+
+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) {
+ /* Check if HSI caused the IO wakeup */
+ if (omap_hsi_is_io_wakeup_from_hsi()) {
+ omap_pm_clear_dsp_wake_up();
+ omap_hsi_wakeup(0);
+ }
+ omap_uart_resume_idle();
+ usbhs_wakeup();
+ omap_debug_uart_resume_idle();
+ 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;
+}
+
+/**
+ * omap_default_idle() - implement a default idle for !CONFIG_CPUIDLE
+ *
+ * Implements OMAP4 memory, IO ordering requirements which can't be addressed
+ * with default arch_idle() hook. Used by all CPUs with !CONFIG_CPUIDLE and
+ * by secondary CPU with CONFIG_CPUIDLE.
+ */
+static void omap_default_idle(void)
+{
+ local_irq_disable();
+ local_fiq_disable();
+
+ omap_do_wfi();
+
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+/**
+ * omap4_device_set_state_off() - setup device off state
+ * @enable: set to off or not.
+ *
+ * When Device OFF is enabled, Device is allowed to perform
+ * transition to off mode as soon as all power domains in MPU, IVA
+ * and CORE voltage are in OFF or OSWR state (open switch retention)
+ */
+void omap4_device_set_state_off(u8 enable)
+{
+#ifdef CONFIG_OMAP_ALLOW_OSWR
+ if (enable)
+ omap4_prminst_write_inst_reg(0x1 <<
+ OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
+ OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+ else
+#endif
+ omap4_prminst_write_inst_reg(0x0 <<
+ OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
+ OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+}
+
+/**
+ * omap4_device_prev_state_off:
+ * returns true if the device hit OFF mode
+ * This is API to check whether OMAP is waking up from device OFF mode.
+ * There is no other status bit available for SW to read whether last state
+ * entered was device OFF. To work around this, CORE PD, RFF context state
+ * is used which is lost only when we hit device OFF state
+ */
+bool omap4_device_prev_state_off(void)
+{
+ u32 reg;
+
+ reg = omap4_prminst_read_inst_reg(core_pwrdm->prcm_partition,
+ core_pwrdm->prcm_offs,
+ OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET)
+ & OMAP4430_LOSTCONTEXT_RFF_MASK;
+
+ return reg ? true : false;
+}
+
+void omap4_device_clear_prev_off_state(void)
+{
+ omap4_prminst_write_inst_reg(OMAP4430_LOSTCONTEXT_RFF_MASK |
+ OMAP4430_LOSTCONTEXT_DFF_MASK,
+ core_pwrdm->prcm_partition,
+ core_pwrdm->prcm_offs,
+ OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET);
+}
+
+/**
+ * omap4_device_next_state_off:
+ * returns true if the device next state is OFF
+ * This is API to check whether OMAP is programmed for device OFF
+ */
+bool omap4_device_next_state_off(void)
+{
+ return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET)
+ & OMAP4430_DEVICE_OFF_ENABLE_MASK ? true : false;
+}
+
+static void __init omap4_pm_setup_errata(void)
+{
+ /*
+ * Current understanding is that the following errata impacts
+ * all OMAP4 silica
+ */
+ if (cpu_is_omap44xx())
+ pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX;
+ /* Dynamic Dependency errata for all silicon !=443x */
+ if (cpu_is_omap443x())
+ pm44xx_errata |= OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_i688;
+ else
+ pm44xx_errata |= OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_IDLE_iXXX;
}
/**
@@ -98,23 +1217,173 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
*/
static int __init omap4_pm_init(void)
{
- int ret;
+ int ret = 0;
+ struct clockdomain *l3_1_clkdm;
+ struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per, *l4_cfg;
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");
+ /* setup the erratas */
+ omap4_pm_setup_errata();
+
+ prcm_setup_regs();
+ syscontrol_setup_regs();
+
+ ret = request_irq(OMAP44XX_IRQ_PRCM,
+ (irq_handler_t)prcm_interrupt_handler,
+ IRQF_NO_SUSPEND | 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;
}
+ /*
+ * On 4430:
+ * 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.
+ *
+ * On 4460:
+ * The dynamic dependency between MPUSS -> MEMIF doesn't work
+ * as expected if MPUSS OSWR is enabled in idle.
+ * The dynamic dependency between MPUSS -> L4 PER & CFG
+ * doesn't work as expected. The hardware recommendation is
+ * to keep above dependencies. Without this system locks up or
+ * randomly crashes.
+ */
+ 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");
+ l4_per = clkdm_lookup("l4_per_clkdm");
+ l4_cfg = clkdm_lookup("l4_cfg_clkdm");
+ if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
+ (!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per) || (!l4_cfg))
+ goto err2;
+
+ /* if we cannot ever enable static dependency. */
+ if (is_pm44xx_erratum(MPU_EMIF_NO_DYNDEP_i688))
+ ret |= clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
+
+ if (cpu_is_omap443x()) {
+ 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);
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per);
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l4_cfg);
+ ret |= clkdm_add_wkdep(ducati_clkdm, l4_per);
+ ret |= clkdm_add_wkdep(ducati_clkdm, l4_cfg);
+ if (ret) {
+ pr_err("Failed to add MPUSS -> L3/EMIF, DUCATI -> L3"
+ " and MPUSS -> L4* wakeup dependency\n");
+ goto err2;
+ }
+ pr_info("OMAP4 PM: Static dependency added between"
+ " MPUSS <-> EMIF, MPUSS <-> L4_PER/CFG"
+ " MPUSS <-> L3_MAIN_1.\n");
+ pr_info("OMAP4 PM: Static dependency added between"
+ " DUCATI <-> L4_PER/CFG and DUCATI <-> L3.\n");
+ } else if (cpu_is_omap446x()) {
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per);
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l4_cfg);
+
+ /* There appears to be a problem between the MPUSS and L3_1 */
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm);
+
+ /* There appears to be a problem between the Ducati and L3/L4 */
+ ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm);
+ ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
+ ret |= clkdm_add_wkdep(ducati_clkdm, l4_per);
+ ret |= clkdm_add_wkdep(ducati_clkdm, l4_cfg);
+
+ if (ret) {
+ pr_err("Failed to add MPUSS and DUCATI -> "
+ "L4* and L3_1 wakeup dependency\n");
+ goto err2;
+ }
+ pr_info("OMAP4 PM: Static dependency added between"
+ " MPUSS and DUCATI <-> L4_PER/CFG and L3_1.\n");
+ }
+
+ (void) clkdm_for_each(clkdms_setup, NULL);
+
+ /* Get handles for VDD's for enabling/disabling SR */
+ mpu_voltdm = voltdm_lookup("mpu");
+ if (!mpu_voltdm) {
+ pr_err("%s: Failed to get voltdm for VDD MPU\n", __func__);
+ goto err2;
+ }
+ omap_vc_set_auto_trans(mpu_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
+
+ iva_voltdm = voltdm_lookup("iva");
+ if (!iva_voltdm) {
+ pr_err("%s: Failed to get voltdm for VDD IVA\n", __func__);
+ goto err2;
+ }
+ omap_vc_set_auto_trans(iva_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
+
+ core_voltdm = voltdm_lookup("core");
+ if (!core_voltdm) {
+ pr_err("%s: Failed to get voltdm for VDD CORE\n", __func__);
+ goto err2;
+ }
+ omap_vc_set_auto_trans(core_voltdm,
+ OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
+
+ 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");
+ tesla_pwrdm = pwrdm_lookup("tesla_pwrdm");
+ if (!tesla_pwrdm)
+ pr_err("%s: Failed to lookup tesla_pwrdm\n", __func__);
+
+ tesla_clkdm = clkdm_lookup("tesla_clkdm");
+ if (!tesla_clkdm)
+ pr_err("%s: Failed to lookup tesla_clkdm\n", __func__);
+
+ /* Enable wakeup for PRCM IRQ for system wide suspend */
+ enable_irq_wake(OMAP44XX_IRQ_PRCM);
+
+ /* Overwrite the default arch_idle() */
+ pm_idle = omap_default_idle;
+
+ omap4_idle_init();
+
+ omap_pm_is_ready_status = true;
+ /* let the other CPU know as well */
+ smp_wmb();
+
err2:
return ret;
}
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9af0847..5aff165 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"
@@ -76,7 +78,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,19 +96,44 @@ 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 */
- for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
- pwrdm->state_counter[i] = 0;
+ /*
+ * Program all powerdomain target state as ON; This is to
+ * prevent domains from hitting low power states (if bootloader
+ * has target states set to something other than ON) and potentially
+ * even losing context while PM is not fully initilized.
+ * The PM late init code can then program the desired target
+ * state for all the power domains.
+ */
+ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_ON);
- pwrdm->ret_logic_off_counter = 0;
- for (i = 0; i < pwrdm->banks; i++)
- pwrdm->ret_mem_off_counter[i] = 0;
+ /* Initialize the powerdomain's state counter */
+ memset(&pwrdm->count, 0, sizeof(pwrdm->count));
+ memset(&pwrdm->last_count, 0, sizeof(pwrdm->last_count));
+ memset(&pwrdm->time, 0, sizeof(pwrdm->time));
+ memset(&pwrdm->last_time, 0, sizeof(pwrdm->last_time));
pwrdm_wait_transition(pwrdm);
pwrdm->state = pwrdm_read_pwrst(pwrdm);
- pwrdm->state_counter[pwrdm->state] = 1;
+ pwrdm->count.state[pwrdm->state] = 1;
+
+ /* Initialize priority ordered list for wakeup latency constraint */
+ spin_lock_init(&pwrdm->wakeuplat_lock);
+ plist_head_init(&pwrdm->wakeuplat_dev_list);
+
+ /* res_mutex protects res_list add and del ops */
+ mutex_init(&pwrdm->wakeuplat_mutex);
pr_debug("powerdomain: registered %s\n", pwrdm->name);
@@ -119,16 +146,18 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
u8 prev_logic_pwrst, prev_mem_pwrst;
prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
+
+ /* Fake logic off counter */
if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
- (prev_logic_pwrst == PWRDM_POWER_OFF))
- pwrdm->ret_logic_off_counter++;
+ (pwrdm_read_logic_retst(pwrdm) == PWRDM_POWER_OFF))
+ pwrdm->count.ret_logic_off++;
for (i = 0; i < pwrdm->banks; i++) {
prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) &&
(prev_mem_pwrst == PWRDM_POWER_OFF))
- pwrdm->ret_mem_off_counter[i]++;
+ pwrdm->count.ret_mem_off[i]++;
}
}
@@ -149,7 +178,7 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
case PWRDM_STATE_PREV:
prev = pwrdm_read_prev_pwrst(pwrdm);
if (pwrdm->state != prev)
- pwrdm->state_counter[prev]++;
+ pwrdm->count.state[prev]++;
if (prev == PWRDM_POWER_RET)
_update_logic_membank_counters(pwrdm);
/*
@@ -169,7 +198,7 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
}
if (state != prev)
- pwrdm->state_counter[state]++;
+ pwrdm->count.state[state]++;
pm_dbg_update_time(pwrdm, prev);
@@ -196,7 +225,7 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
/**
* pwrdm_init - set up the powerdomain layer
* @pwrdm_list: array of struct powerdomain pointers to register
- * @custom_funcs: func pointers for arch specific implementations
+ * @custom_funcs: func pointers for arch specfic implementations
*
* Loop through the array of powerdomains @pwrdm_list, registering all
* that are available on the current CPU. If pwrdm_list is supplied
@@ -208,6 +237,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 +413,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 *
*
@@ -935,25 +977,31 @@ int pwrdm_post_transition(void)
* @pwrdm: struct powerdomain * to wait for
*
* Context loss count is the sum of powerdomain off-mode counter, the
- * logic off counter and the per-bank memory off counter. Returns 0
+ * logic off counter and the per-bank memory off counter. Returns negative
* (and WARNs) upon error, otherwise, returns the context loss count.
*/
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
{
int i, count;
if (!pwrdm) {
WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
- return 0;
+ return -ENODEV;
}
- count = pwrdm->state_counter[PWRDM_POWER_OFF];
- count += pwrdm->ret_logic_off_counter;
+ count = pwrdm->count.state[PWRDM_POWER_OFF];
+ count += pwrdm->count.ret_logic_off;
for (i = 0; i < pwrdm->banks; i++)
- count += pwrdm->ret_mem_off_counter[i];
+ count += pwrdm->count.ret_mem_off[i];
- pr_debug("powerdomain: %s: context loss count = %u\n",
+ /*
+ * 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;
+
+ pr_debug("powerdomain: %s: context loss count = %d\n",
pwrdm->name, count);
return count;
@@ -999,3 +1047,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);
+ spin_lock(&pwrdm->wakeuplat_lock);
+ plist_add(&user->node, &pwrdm->wakeuplat_dev_list);
+ spin_unlock(&pwrdm->wakeuplat_lock);
+ 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;
+ }
+
+ spin_lock(&pwrdm->wakeuplat_lock);
+ plist_del(&user->node, &pwrdm->wakeuplat_dev_list);
+ spin_unlock(&pwrdm->wakeuplat_lock);
+ 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 next 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;
+ }
+
+ if (pwrdm_read_next_pwrst(pwrdm) != 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 d23d979..59aef2b 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,33 @@
/* 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_count_stats {
+ unsigned state[PWRDM_MAX_PWRSTS];
+ unsigned ret_logic_off;
+ unsigned ret_mem_off[PWRDM_MAX_MEM_BANKS];
+};
+
+struct powerdomain_time_stats {
+ s64 state[PWRDM_MAX_PWRSTS];
+};
+
/**
* 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 +127,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,15 +154,27 @@ 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;
- unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
+
+ struct powerdomain_count_stats count;
+ struct powerdomain_count_stats last_count;
#ifdef CONFIG_PM_DEBUG
s64 timer;
- s64 state_timer[PWRDM_MAX_PWRSTS];
+ struct powerdomain_time_stats time;
+ struct powerdomain_time_stats last_time;
#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 +233,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);
@@ -207,7 +265,7 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
int pwrdm_pre_transition(void);
int pwrdm_post_transition(void);
int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
extern void omap2xxx_powerdomains_init(void);
@@ -226,5 +284,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/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index a7880af..c0aab2a 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -19,9 +19,13 @@
#include "powerdomain.h"
#include <plat/prcm.h>
#include "prm2xxx_3xxx.h"
+#include "cminst44xx.h"
#include "prm44xx.h"
+#include "prcm44xx.h"
#include "prminst44xx.h"
#include "prm-regbits-44xx.h"
+#include "cm-regbits-44xx.h"
+#include "cm2_44xx.h"
static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
{
@@ -207,6 +211,41 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
return 0;
}
+static int omap4_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
+{
+ /*
+ * FIXME: This should be fixed right way by moving it into HWMOD
+ * or clock framework since sar control is moved to module level
+ */
+ omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+ 1 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+ OMAP4430_CM2_L3INIT_INST,
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET);
+ omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+ 1 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+ OMAP4430_CM2_L3INIT_INST,
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET);
+ return 0;
+}
+
+static int omap4_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
+{
+ /*
+ * FIXME: This should be fixed right way by moving it into HWMOD
+ * or clock framework since sar control is moved to module level
+ */
+ omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+ 0 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+ OMAP4430_CM2_L3INIT_INST,
+ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET);
+ omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+ 0 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+ OMAP4430_CM2_L3INIT_INST,
+ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET);
+
+ return 0;
+}
+
struct pwrdm_ops omap4_pwrdm_operations = {
.pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
.pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
@@ -222,4 +261,6 @@ struct pwrdm_ops omap4_pwrdm_operations = {
.pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
.pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
.pwrdm_wait_transition = omap4_pwrdm_wait_transition,
+ .pwrdm_enable_hdwr_sar = omap4_pwrdm_enable_hdwr_sar,
+ .pwrdm_disable_hdwr_sar = omap4_pwrdm_disable_hdwr_sar,
};
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..d645d68 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,16 +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,
- .pwrsts_logic_ret = PWRSTS_OFF,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+ .pwrsts = PWRSTS_OFF_RET_INA_ON,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRSTS_RET, /* aessmem */
@@ -91,16 +105,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,
- .pwrsts_logic_ret = PWRSTS_OFF,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+ .pwrsts = PWRSTS_OFF_RET_INA_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF, /* dss_mem */
@@ -109,15 +129,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 +158,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 +186,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 +199,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,15 +223,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),
- .pwrsts = PWRSTS_OFF_ON,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF, /* emu_bank */
@@ -200,12 +248,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,16 +267,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,
- .pwrsts_logic_ret = PWRSTS_OFF,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX),
+ .pwrsts = PWRSTS_OFF_RET_INA_ON,
.banks = 4,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF, /* hwa_mem */
@@ -242,15 +322,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 +346,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_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
.pwrsts_mem_ret = {
@@ -276,16 +370,23 @@ static struct powerdomain l3init_44xx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* l3init_bank1 */
},
- .flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
+ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE | PWRDM_HAS_HDWR_SAR,
+ .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 +398,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 +412,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 +448,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/prcm-debug.c b/arch/arm/mach-omap2/prcm-debug.c
new file mode 100644
index 0000000..bbc6743
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm-debug.c
@@ -0,0 +1,1688 @@
+/*
+ * OMAP4 PRCM Debugging
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "prcm-debug.h"
+#include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prm44xx.h"
+#include "prminst44xx.h"
+#include "cm44xx.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "cm-regbits-44xx.h"
+#include "cminst44xx.h"
+#include "prcm_mpu44xx.h"
+#include "powerdomain.h"
+
+/* DPLLs */
+
+struct d_dpll_info {
+ char *name;
+ void *idlestreg;
+ struct d_dpll_derived *derived[];
+};
+
+struct d_dpll_derived {
+ char *name;
+ void *gatereg;
+ u32 gatemask;
+};
+
+static struct d_dpll_derived derived_dpll_per_m2 = {
+ .name = "DPLL_PER_M2",
+ .gatereg = OMAP4430_CM_DIV_M2_DPLL_PER,
+ .gatemask = 0xa00,
+};
+
+static struct d_dpll_derived derived_dpll_per_m3 = {
+ .name = "DPLL_PER_M3",
+ .gatereg = OMAP4430_CM_DIV_M3_DPLL_PER,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_per_m4 = {
+ .name = "DPLL_PER_M4",
+ .gatereg = OMAP4430_CM_DIV_M4_DPLL_PER,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_per_m5 = {
+ .name = "DPLL_PER_M5",
+ .gatereg = OMAP4430_CM_DIV_M5_DPLL_PER,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_per_m6 = {
+ .name = "DPLL_PER_M6",
+ .gatereg = OMAP4430_CM_DIV_M6_DPLL_PER,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_per_m7 = {
+ .name = "DPLL_PER_M7",
+ .gatereg = OMAP4430_CM_DIV_M7_DPLL_PER,
+ .gatemask = 0x200,
+};
+
+
+static struct d_dpll_info dpll_per = {
+ .name = "DPLL_PER",
+ .idlestreg = OMAP4430_CM_IDLEST_DPLL_PER,
+ .derived = {&derived_dpll_per_m2, &derived_dpll_per_m3,
+ &derived_dpll_per_m4, &derived_dpll_per_m5,
+ &derived_dpll_per_m6, &derived_dpll_per_m7,
+ NULL},
+};
+
+static struct d_dpll_derived derived_dpll_core_m2 = {
+ .name = "DPLL_CORE_M2",
+ .gatereg = OMAP4430_CM_DIV_M2_DPLL_CORE,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_core_m3 = {
+ .name = "DPLL_CORE_M3",
+ .gatereg = OMAP4430_CM_DIV_M3_DPLL_CORE,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_core_m4 = {
+ .name = "DPLL_CORE_M4",
+ .gatereg = OMAP4430_CM_DIV_M4_DPLL_CORE,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_core_m5 = {
+ .name = "DPLL_CORE_M5",
+ .gatereg = OMAP4430_CM_DIV_M5_DPLL_CORE,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_core_m6 = {
+ .name = "DPLL_CORE_M6",
+ .gatereg = OMAP4430_CM_DIV_M6_DPLL_CORE,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_derived derived_dpll_core_m7 = {
+ .name = "DPLL_CORE_M7",
+ .gatereg = OMAP4430_CM_DIV_M7_DPLL_CORE,
+ .gatemask = 0x200,
+};
+
+static struct d_dpll_info dpll_core = {
+ .name = "DPLL_CORE",
+ .idlestreg = OMAP4430_CM_IDLEST_DPLL_CORE,
+ .derived = {&derived_dpll_core_m2, &derived_dpll_core_m3,
+ &derived_dpll_core_m4, &derived_dpll_core_m5,
+ &derived_dpll_core_m6, &derived_dpll_core_m7,
+ NULL},
+};
+
+static struct d_dpll_info dpll_abe = {
+ .name = "DPLL_ABE",
+ .idlestreg = OMAP4430_CM_IDLEST_DPLL_ABE,
+ .derived = {/* &derived_dpll_abe_m2, &derived_dpll_abe_m3,
+ &derived_dpll_abe_m4, &derived_dpll_abe_m5,
+ &derived_dpll_abe_m6, &derived_dpll_abe_m7,
+ */ NULL},
+};
+
+static struct d_dpll_info dpll_mpu = {
+ .name = "DPLL_MPU",
+ .idlestreg = OMAP4430_CM_IDLEST_DPLL_MPU,
+ .derived = {/* &derived_dpll_mpu_m2, */ NULL},
+};
+
+static struct d_dpll_info dpll_iva = {
+ .name = "DPLL_IVA",
+ .idlestreg = OMAP4430_CM_IDLEST_DPLL_IVA,
+ .derived = {/* &derived_dpll_iva_m4, &derived_dpll_iva_m5, */ NULL},
+};
+
+static struct d_dpll_info dpll_usb = {
+ .name = "DPLL_USB",
+ .idlestreg = OMAP4430_CM_IDLEST_DPLL_USB,
+ .derived = {/* &derived_dpll_usb_m2, */ NULL},
+};
+
+
+/* Other internal generators */
+
+struct d_intgen_info {
+ char *name;
+ void *gatereg;
+ u32 gatemask;
+};
+
+static struct d_intgen_info intgen_cm1_abe = {
+ .name = "CM1_ABE",
+ .gatereg = OMAP4430_CM_CLKSEL_ABE,
+ .gatemask = 0x500,
+};
+
+
+
+/* Modules */
+
+#define MOD_MASTER (1 << 0)
+#define MOD_SLAVE (1 << 1)
+#define MOD_MODE (1 << 2)
+
+struct d_mod_info {
+ char *name;
+ void *clkctrl;
+ int flags;
+ int optclk;
+};
+
+static struct d_mod_info mod_debug = {
+ .name = "DEBUG",
+ .clkctrl = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_bandgap = {
+ .name = "BANDGAP",
+ .clkctrl = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ .flags = 0,
+ .optclk = 0x100,
+};
+
+static struct d_mod_info mod_gpio1 = {
+ .name = "GPIO1",
+ .clkctrl = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+
+static struct d_mod_info mod_keyboard = {
+ .name = "KEYBOARD",
+ .clkctrl = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_sar_ram = {
+ .name = "SAR_RAM",
+ .clkctrl = OMAP4430_CM_WKUP_SARRAM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_32ktimer = {
+ .name = "32KTIMER",
+ .clkctrl = OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_gptimer1 = {
+ .name = "GPTIMER1",
+ .clkctrl = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_wdtimer2 = {
+ .name = "WDTIMER2",
+ .clkctrl = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_l4_wkup = {
+ .name = "L4_WKUP",
+ .clkctrl = OMAP4430_CM_WKUP_L4WKUP_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_sr_core = {
+ .name = "SR_CORE",
+ .clkctrl = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_sr_iva = {
+ .name = "SR_IVA",
+ .clkctrl = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_sr_mpu = {
+ .name = "SR_MPU",
+ .clkctrl = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_fdif = {
+ .name = "FACE DETECT",
+ .clkctrl = OMAP4430_CM_CAM_FDIF_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER| MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_iss = {
+ .name = "ISS",
+ .clkctrl = OMAP4430_CM_CAM_ISS_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER| MOD_SLAVE,
+ .optclk = 0x100,
+};
+
+static struct d_mod_info mod_spinlock = {
+ .name = "SPINLOCK",
+ .clkctrl = OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_l4_cfg_interconnect = {
+ .name = "L4_CFG interconnect",
+ .clkctrl = OMAP4430_CM_L4CFG_L4_CFG_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_mailbox = {
+ .name = "MAILBOX",
+ .clkctrl = OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_sar_rom = {
+ .name = "SAR_ROM",
+ .clkctrl = OMAP4430_CM_L4CFG_SAR_ROM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_dmm = {
+ .name = "DMM",
+ .clkctrl = OMAP4430_CM_MEMIF_DMM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_emif_1 = {
+ .name = "EMIF_1",
+ .clkctrl = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_emif_2 = {
+ .name = "EMIF_2",
+ .clkctrl = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_emif_fw = {
+ .name = "EMIF_FW",
+ .clkctrl = OMAP4430_CM_MEMIF_EMIF_FW_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_dll = {
+ .name = "DLL",
+ .clkctrl = OMAP4430_CM_MEMIF_DLL_CLKCTRL,
+ .flags = 0,
+ .optclk = 0x100,
+};
+
+static struct d_mod_info mod_cortexm3 = {
+ .name = "CORTEXM3",
+ .clkctrl = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_gpmc = {
+ .name = "GPMC",
+ .clkctrl = OMAP4430_CM_L3_2_GPMC_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_l3_2_interconnect = {
+ .name = "L3_2 interconnect",
+ .clkctrl = OMAP4430_CM_L3_2_L3_2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_ocmc_ram = {
+ .name = "OCMC_RAM",
+ .clkctrl = OMAP4430_CM_L3_2_OCMC_RAM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_l3_3_interconnect = {
+ .name = "L3_3 interconnect",
+ .clkctrl = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_l3_instr_interconnect = {
+ .name = "L3_INSTR interconnect",
+ .clkctrl = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_wp1 = {
+ .name = "WP1",
+ .clkctrl = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_l3_1_interconnect = {
+ .name = "L3_1 interconnect",
+ .clkctrl = OMAP4430_CM_L3_1_L3_1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_c2c = {
+ .name = "C2C",
+ .clkctrl = OMAP4430_CM_D2D_SAD2D_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_c2c_fw = {
+ .name = "C2C_FW",
+ .clkctrl = OMAP4430_CM_D2D_SAD2D_FW_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+
+static struct d_mod_info mod_sdma = {
+ .name = "sDMA",
+ .clkctrl = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_dss = {
+ .name = "DSS",
+ .clkctrl = OMAP4430_CM_DSS_DSS_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0xf00,
+};
+
+static struct d_mod_info mod_sgx = {
+ .name = "SGX",
+ .clkctrl = OMAP4430_CM_GFX_GFX_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_hsi = {
+ .name = "HSI",
+ .clkctrl = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_hsmmc1 = {
+ .name = "HSMMC1",
+ .clkctrl = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_hsmmc2 = {
+ .name = "HSMMC2",
+ .clkctrl = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_usbphy = {
+ .name = "USBPHY",
+ .clkctrl = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+
+static struct d_mod_info mod_fsusb = {
+ .name = "FSUSB",
+ .clkctrl = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_hsusbhost = {
+ .name = "HSUSBHOST",
+ .clkctrl = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0xff00,
+};
+
+static struct d_mod_info mod_hsusbotg = {
+ .name = "HSUSBOTG",
+ .clkctrl = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x100,
+};
+
+static struct d_mod_info mod_usbtll = {
+ .name = "USBTLL",
+ .clkctrl = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x300,
+};
+
+static struct d_mod_info mod_gptimer10 = {
+ .name = "GPTIMER10",
+ .clkctrl = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_gptimer11 = {
+ .name = "GPTIMER11",
+ .clkctrl = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer2 = {
+ .name = "GPTIMER2",
+ .clkctrl = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer3 = {
+ .name = "GPTIMER3",
+ .clkctrl = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer4 = {
+ .name = "GPTIMER4",
+ .clkctrl = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer9 = {
+ .name = "GPTIMER9",
+ .clkctrl = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_elm = {
+ .name = "ELM",
+ .clkctrl = OMAP4430_CM_L4PER_ELM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gpio2 = {
+ .name = "GPIO2",
+ .clkctrl = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+static struct d_mod_info mod_gpio3 = {
+ .name = "GPIO3",
+ .clkctrl = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+static struct d_mod_info mod_gpio4 = {
+ .name = "GPIO4",
+ .clkctrl = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+static struct d_mod_info mod_gpio5 = {
+ .name = "GPIO5",
+ .clkctrl = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+static struct d_mod_info mod_gpio6 = {
+ .name = "GPIO6",
+ .clkctrl = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x100,
+};
+static struct d_mod_info mod_hdq = {
+ .name = "HDQ",
+ .clkctrl = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_i2c1 = {
+ .name = "I2C1",
+ .clkctrl = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_i2c2 = {
+ .name = "I2C2",
+ .clkctrl = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_i2c3 = {
+ .name = "I2C3",
+ .clkctrl = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_i2c4 = {
+ .name = "I2C4",
+ .clkctrl = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_l4_per_interconnect = {
+ .name = "L4_PER interconnect",
+ .clkctrl = OMAP4430_CM_L4PER_L4PER_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcbsp4 = {
+ .name = "MCBSP4",
+ .clkctrl = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcspi1 = {
+ .name = "MCSPI1",
+ .clkctrl = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcspi2 = {
+ .name = "MCSPI2",
+ .clkctrl = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcspi3 = {
+ .name = "MCSPI3",
+ .clkctrl = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcspi4 = {
+ .name = "MCSPI4",
+ .clkctrl = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_hsmmc3 = {
+ .name = "HSMMC3",
+ .clkctrl = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_hsmmc4 = {
+ .name = "HSMMC4",
+ .clkctrl = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_hsmmc5 = {
+ .name = "HSMMC5",
+ .clkctrl = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_slimbus2 = {
+ .name = "SLIMBUS2",
+ .clkctrl = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x700,
+};
+static struct d_mod_info mod_uart1 = {
+ .name = "UART1",
+ .clkctrl = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_uart2 = {
+ .name = "UART2",
+ .clkctrl = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_uart3 = {
+ .name = "UART3",
+ .clkctrl = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_uart4 = {
+ .name = "UART4",
+ .clkctrl = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_audio_engine = {
+ .name = "AUDIO ENGINE",
+ .clkctrl = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_dmic = {
+ .name = "DMIC",
+ .clkctrl = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_l4_abe_interconnect = {
+ .name = "L4_ABE interconnect",
+ .clkctrl = OMAP4430_CM1_ABE_L4ABE_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcasp1 = {
+ .name = "MCASP1",
+ .clkctrl = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcbsp1 = {
+ .name = "MCBSP1",
+ .clkctrl = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcbsp2 = {
+ .name = "MCBSP2",
+ .clkctrl = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcbsp3 = {
+ .name = "MCBSP3",
+ .clkctrl = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_mcpdm = {
+ .name = "MCPDM",
+ .clkctrl = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_slimbus1 = {
+ .name = "SLIMBUS1",
+ .clkctrl = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0xf00,
+};
+static struct d_mod_info mod_gptimer5 = {
+ .name = "GPTIMER5",
+ .clkctrl = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer6 = {
+ .name = "GPTIMER6",
+ .clkctrl = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer7 = {
+ .name = "GPTIMER7",
+ .clkctrl = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_gptimer8 = {
+ .name = "GPTIMER8",
+ .clkctrl = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_wdtimer3 = {
+ .name = "WDTIMER3",
+ .clkctrl = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_ivahd = {
+ .name = "IVAHD",
+ .clkctrl = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+static struct d_mod_info mod_sl2 = {
+ .name = "SL2",
+ .clkctrl = OMAP4430_CM_IVAHD_SL2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_dsp = {
+ .name = "DSP",
+ .clkctrl = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_cortexa9 = {
+ .name = "CORTEXA9",
+ .clkctrl = OMAP4430_CM_MPU_MPU_CLKCTRL,
+ .flags = MOD_MODE | MOD_MASTER | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+/* L4SEC modules not in TRM, below based on Linux code */
+
+static struct d_mod_info mod_aes1 = {
+ .name = "AES1",
+ .clkctrl = OMAP4430_CM_L4SEC_AES1_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_aes2 = {
+ .name = "AES2",
+ .clkctrl = OMAP4430_CM_L4SEC_AES2_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_des3des = {
+ .name = "DES3DES",
+ .clkctrl = OMAP4430_CM_L4SEC_DES3DES_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_pkaeip29 = {
+ .name = "PKAEIP29",
+ .clkctrl = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_rng = {
+ .name = "RNG",
+ .clkctrl = OMAP4430_CM_L4SEC_RNG_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_sha2md51 = {
+ .name = "SHA2MD51",
+ .clkctrl = OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+static struct d_mod_info mod_cryptodma = {
+ .name = "CRYPTODMA",
+ .clkctrl = OMAP4430_CM_L4SEC_CRYPTODMA_CLKCTRL,
+ .flags = MOD_MODE | MOD_SLAVE,
+ .optclk = 0x0,
+};
+
+/* Clock domains */
+
+struct d_clkd_info {
+ char *name;
+ const u8 prcm_partition;
+ const s16 cm_inst;
+ const u16 clkdm_offs;
+ int activity;
+ struct d_dpll_info *dplls[20];
+ struct d_intgen_info *intgens[20];
+ struct d_mod_info *mods[];
+};
+
+static struct d_clkd_info cd_emu = {
+ .name = "CD_EMU",
+ .prcm_partition = OMAP4430_PRM_PARTITION,
+ .cm_inst = OMAP4430_PRM_EMU_CM_INST,
+ .clkdm_offs = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
+ .activity = 0x300,
+ .mods = {&mod_debug, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: CM1_EMU
+};
+
+static struct d_clkd_info cd_wkup = {
+ .name = "CD_WKUP",
+ .prcm_partition = OMAP4430_PRM_PARTITION,
+ .cm_inst = OMAP4430_PRM_WKUP_CM_INST,
+ .clkdm_offs = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
+ .activity = 0x1b00,
+ .mods = {&mod_bandgap, &mod_gpio1, &mod_keyboard, &mod_sar_ram,
+ &mod_32ktimer, &mod_gptimer1, &mod_wdtimer2,
+ &mod_l4_wkup, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: SYSCTRL_PADCONF_WKUP, SYSCTRL_GENERAL_WKUP, PRM,
+ // SCRM
+};
+
+static struct d_clkd_info cd_l4_alwon_core = {
+ .name = "CD_L4_ALWON_CORE",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_ALWAYS_ON_INST,
+ .clkdm_offs = OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS,
+ .activity = 0xf00,
+ .mods = {&mod_sr_core, &mod_sr_iva, &mod_sr_mpu, NULL},
+ .dplls = {&dpll_per, &dpll_core, &dpll_abe, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: CM1, CORTEXM3_WKUPGEN, SDMA_WKUPGEN, SPINNER
+};
+
+static struct d_clkd_info cd_cam = {
+ .name = "CD_CAM",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CAM_INST,
+ .clkdm_offs = OMAP4430_CM2_CAM_CAM_CDOFFS,
+ .activity = 0x700,
+ .mods = {&mod_fdif, &mod_iss, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_l4_cfg = {
+ .name = "CD_L4_CFG",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_spinlock, &mod_l4_cfg_interconnect, &mod_mailbox,
+ &mod_sar_rom, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: SYSCTRL_PADCONF_CORE, SYSCTRL_GENERAL_CORE
+};
+
+static struct d_clkd_info cd_emif = {
+ .name = "CD_EMIF",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
+ .activity = 0x700,
+ .mods = {&mod_dmm, &mod_emif_1, &mod_emif_2, &mod_emif_fw,
+ &mod_dll, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: DDRPHY
+};
+
+static struct d_clkd_info cd_cortexm3 = {
+ .name = "CD_CORTEXM3",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_DUCATI_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_cortexm3, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_l3_2 = {
+ .name = "CD_L3_2",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_L3_2_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_gpmc, &mod_l3_2_interconnect, &mod_ocmc_ram, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_l3_instr = {
+ .name = "CD_L3_INSTR",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_L3INSTR_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_l3_3_interconnect, &mod_l3_instr_interconnect,
+ &mod_wp1, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_l3_1 = {
+ .name = "CD_L3_1",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_L3_1_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_l3_1_interconnect, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_c2c = {
+ .name = "CD_C2C",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_D2D_CDOFFS,
+ .activity = 0x700,
+ .mods = {&mod_c2c, &mod_c2c_fw, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_dma = {
+ .name = "CD_DMA",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_CORE_INST,
+ .clkdm_offs = OMAP4430_CM2_CORE_SDMA_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_sdma, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_dss = {
+ .name = "CD_DSS",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_DSS_INST,
+ .clkdm_offs = OMAP4430_CM2_DSS_DSS_CDOFFS,
+ .activity = 0xf00,
+ .mods = {&mod_dss, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_sgx = {
+ .name = "CD_SGX",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_GFX_INST,
+ .clkdm_offs = OMAP4430_CM2_GFX_GFX_CDOFFS,
+ .activity = 0x300,
+ .mods = {&mod_sgx, NULL},
+};
+
+static struct d_clkd_info cd_l3_init = {
+ .name = "CD_L3_INIT",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_L3INIT_INST,
+ .clkdm_offs = OMAP4430_CM2_L3INIT_L3INIT_CDOFFS,
+ .activity = 0x3ef7f300,
+ .mods = {&mod_hsi, &mod_hsmmc1, &mod_hsmmc2, &mod_usbphy,
+ &mod_fsusb, &mod_hsusbhost, &mod_hsusbotg, &mod_usbtll,
+ NULL},
+ .dplls = {&dpll_usb, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: CM1_USB
+};
+
+static struct d_clkd_info cd_l4_per = {
+ .name = "CD_L4_PER",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_L4PER_INST,
+ .clkdm_offs = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
+ .activity = 0x24fff00,
+ .mods = {&mod_gptimer10, &mod_gptimer11, &mod_gptimer2,
+ &mod_gptimer3, &mod_gptimer4, &mod_gptimer9, &mod_elm,
+ &mod_gpio2, &mod_gpio3, &mod_gpio4, &mod_gpio5, &mod_gpio6,
+ &mod_hdq, &mod_i2c1, &mod_i2c2, &mod_i2c3, &mod_i2c4,
+ &mod_l4_per_interconnect, &mod_mcbsp4, &mod_mcspi1,
+ &mod_mcspi2, &mod_mcspi3, &mod_mcspi4, &mod_hsmmc3,
+ &mod_hsmmc4, &mod_hsmmc5, &mod_slimbus2, &mod_uart1,
+ &mod_uart2, &mod_uart3, &mod_uart4, NULL},
+ // TBD: Linux refs: I2C5
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_abe = {
+ .name = "CD_ABE",
+ .prcm_partition = OMAP4430_CM1_PARTITION,
+ .cm_inst = OMAP4430_CM1_ABE_INST,
+ .clkdm_offs = OMAP4430_CM1_ABE_ABE_CDOFFS,
+ .activity = 0x3400,
+ .mods = {&mod_audio_engine, &mod_dmic, &mod_l4_abe_interconnect,
+ &mod_mcasp1, &mod_mcbsp1, &mod_mcbsp2, &mod_mcbsp3,
+ &mod_mcpdm, &mod_slimbus1, &mod_gptimer5, &mod_gptimer6,
+ &mod_gptimer7, &mod_gptimer8, &mod_wdtimer3, NULL},
+ .intgens = {&intgen_cm1_abe, NULL},
+};
+
+static struct d_clkd_info cd_ivahd = {
+ .name = "CD_IVAHD",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_IVAHD_INST,
+ .clkdm_offs = OMAP4430_CM2_IVAHD_IVAHD_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_ivahd, &mod_sl2, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_dsp = {
+ .name = "CD_DSP",
+ .prcm_partition = OMAP4430_CM1_PARTITION,
+ .cm_inst = OMAP4430_CM1_TESLA_INST,
+ .clkdm_offs = OMAP4430_CM1_TESLA_TESLA_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_dsp, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_pd_alwon_mpu_fake = {
+ .name = "N/A (clock generator)",
+ .prcm_partition = -1,
+ .cm_inst = -1,
+ .clkdm_offs = -1,
+ .activity = 0x0,
+ .mods = {NULL},
+ .dplls = {&dpll_mpu, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: CORTEXA9_MPU_INTC
+};
+
+static struct d_clkd_info cd_pd_alwon_dsp_fake = {
+ .name = "N/A (clock generator)",
+ .prcm_partition = -1,
+ .cm_inst = -1,
+ .clkdm_offs = -1,
+ .activity = 0x0,
+ .mods = {NULL},
+ .dplls = {&dpll_iva, NULL},
+ .intgens = {NULL},
+ // TBD: TRM mentions: DSP_WKUPGEN
+};
+
+static struct d_clkd_info cd_cortexa9 = {
+ .name = "CD_CORTEXA9",
+ .prcm_partition = OMAP4430_CM1_PARTITION,
+ .cm_inst = OMAP4430_CM1_MPU_INST,
+ .clkdm_offs = OMAP4430_CM1_MPU_MPU_CDOFFS,
+ .activity = 0x100,
+ .mods = {&mod_cortexa9, NULL},
+ .intgens = {NULL},
+};
+
+static struct d_clkd_info cd_l4sec = {
+ .name = "CD_L4SEC",
+ .prcm_partition = OMAP4430_CM2_PARTITION,
+ .cm_inst = OMAP4430_CM2_L4PER_INST,
+ .clkdm_offs = OMAP4430_CM2_L4PER_L4SEC_CDOFFS,
+ .activity = 0x300,
+ .mods = {&mod_aes1, &mod_aes2, &mod_des3des, &mod_pkaeip29, &mod_rng,
+ &mod_sha2md51, &mod_cryptodma, NULL},
+ .intgens = {NULL},
+};
+
+#if 0 /* Don't appear to be valid */
+/* CD_MPU0 and MPU1 not in TRM, below based on Linux code. */
+
+static struct d_clkd_info cd_mpu0 = {
+ .name = "CD_MPU0",
+ .prcm_partition = OMAP4430_PRCM_MPU_PARTITION,
+ .cm_inst = OMAP4430_PRCM_MPU_CPU0_INST,
+ .clkdm_offs = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
+ .activity = 0x0,
+ .mods = {NULL},
+ .intgens = {NULL}, // TBD: No docs
+};
+
+static struct d_clkd_info cd_mpu1 = {
+ .name = "CD_MPU1",
+ .prcm_partition = OMAP4430_PRCM_MPU_PARTITION,
+ .cm_inst = OMAP4430_PRCM_MPU_CPU1_INST,
+ .clkdm_offs = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
+ .activity = 0x0,
+ .mods = {NULL},
+ .intgens = {NULL}, // TBD: No docs
+};
+#endif
+
+/* Power domains */
+
+struct d_pwrd_info {
+ char *name;
+ long prminst;
+ int pwrst;
+ struct d_clkd_info *cds[];
+};
+
+static struct d_pwrd_info pd_emu = {
+ .name = "PD_EMU",
+ .prminst = OMAP4430_PRM_EMU_INST,
+ .pwrst = OMAP4_PM_EMU_PWRSTST_OFFSET,
+ .cds = {&cd_emu, NULL},
+};
+
+static struct d_pwrd_info pd_wkup = {
+ .name = "PD_WKUP",
+ .prminst = OMAP4430_PRM_WKUP_INST,
+ .pwrst = -1,
+ .cds = {&cd_wkup, NULL},
+};
+
+static struct d_pwrd_info pd_alwon_core = {
+ .name = "PD_ALWON_CORE",
+ .prminst = OMAP4430_PRM_ALWAYS_ON_INST,
+ .pwrst = -1,
+ .cds = {&cd_l4_alwon_core, NULL},
+};
+
+static struct d_pwrd_info pd_cam = {
+ .name = "PD_CAM",
+ .prminst = OMAP4430_PRM_CAM_INST,
+ .pwrst = OMAP4_PM_CAM_PWRSTST_OFFSET,
+ .cds = {&cd_cam, NULL},
+};
+
+static struct d_pwrd_info pd_core = {
+ .name = "PD_CORE",
+ .prminst = OMAP4430_PRM_CORE_INST,
+ .pwrst = OMAP4_PM_CORE_PWRSTST_OFFSET,
+ .cds = {&cd_l4_cfg, &cd_emif, &cd_cortexm3, &cd_l3_2, &cd_l3_instr,
+ &cd_l3_1, &cd_c2c, &cd_dma, NULL},
+ // TBD: TRM mentions: CM2
+};
+
+static struct d_pwrd_info pd_dss = {
+ .name = "PD_DSS",
+ .prminst = OMAP4430_PRM_DSS_INST,
+ .pwrst = OMAP4_PM_DSS_PWRSTST_OFFSET,
+ .cds = {&cd_dss, NULL},
+};
+
+static struct d_pwrd_info pd_sgx = {
+ .name = "PD_SGX",
+ .prminst = OMAP4430_PRM_GFX_INST,
+ .pwrst = OMAP4_PM_GFX_PWRSTST_OFFSET,
+ .cds = {&cd_sgx, NULL},
+};
+
+static struct d_pwrd_info pd_l3_init = {
+ .name = "PD_L3_INIT",
+ .prminst = OMAP4430_PRM_L3INIT_INST,
+ .pwrst = OMAP4_PM_L3INIT_PWRSTST_OFFSET,
+ .cds = {&cd_l3_init, NULL},
+};
+
+static struct d_pwrd_info pd_l4_per = {
+ .name = "PD_L4_PER",
+ .prminst = OMAP4430_PRM_L4PER_INST,
+ .pwrst = OMAP4_PM_L4PER_PWRSTST_OFFSET,
+ .cds = {&cd_l4_per, &cd_l4sec, NULL},
+};
+
+static struct d_pwrd_info pd_std_efuse = {
+ .name = "PD_STD_EFUSE",
+ .prminst = -1,
+ .pwrst = -1,
+ .cds = {NULL},
+};
+
+static struct d_pwrd_info pd_alwon_dsp = {
+ .name = "PD_ALWON_DSP",
+ .prminst = -1,
+ .pwrst = -1,
+ .cds = {&cd_pd_alwon_dsp_fake, NULL},
+};
+
+static struct d_pwrd_info pd_audio = {
+ .name = "PD_AUDIO",
+ .prminst = OMAP4430_PRM_ABE_INST,
+ .pwrst = OMAP4_PM_ABE_PWRSTST_OFFSET,
+ .cds = {&cd_abe, NULL},
+};
+
+static struct d_pwrd_info pd_ivahd = {
+ .name = "PD_IVAHD",
+ .prminst = OMAP4430_PRM_IVAHD_INST,
+ .pwrst = OMAP4_PM_IVAHD_PWRSTST_OFFSET,
+ .cds = {&cd_ivahd, NULL},
+};
+
+static struct d_pwrd_info pd_dsp = {
+ .name = "PD_DSP",
+ .prminst = OMAP4430_PRM_TESLA_INST,
+ .pwrst = OMAP4_PM_TESLA_PWRSTST_OFFSET,
+ .cds = {&cd_dsp, NULL},
+};
+
+static struct d_pwrd_info pd_alwon_mpu = {
+ .name = "PD_ALWON_MPU",
+ .prminst = -1,
+ .pwrst = -1,
+ .cds = {&cd_pd_alwon_mpu_fake, NULL},
+};
+
+static struct d_pwrd_info pd_mpu = {
+ .name = "PD_MPU",
+ .prminst = OMAP4430_PRM_MPU_INST,
+ .pwrst = OMAP4_PM_MPU_PWRSTST_OFFSET,
+ .cds = {&cd_cortexa9, NULL},
+};
+
+#if 0 /* Do not seem to be valid */
+/* CPU0 and CPU1 power domains not in TRM, below based on Linux code */
+
+static struct d_pwrd_info pd_cpu0 = {
+ .name = "PD_CPU0",
+ .prminst = OMAP4430_PRCM_MPU_CPU0_INST,
+ .pwrst = OMAP4_PM_CPU0_PWRSTST_OFFSET,
+ .cds = {&cd_mpu0, NULL},
+};
+
+static struct d_pwrd_info pd_cpu1 = {
+ .name = "PD_CPU1",
+ .prminst = OMAP4430_PRCM_MPU_CPU1_INST,
+ .pwrst = OMAP4_PM_CPU1_PWRSTST_OFFSET,
+ .cds = {&cd_mpu1, NULL},
+};
+#endif
+
+/* Voltage domains to power domains */
+
+static struct d_pwrd_info *ldo_wakeup_pds[] =
+{&pd_emu, &pd_wkup, NULL};
+
+static struct d_pwrd_info *vdd_core_pds[] =
+{&pd_alwon_core, &pd_cam, &pd_core, &pd_dss, &pd_sgx, &pd_l3_init, &pd_l4_per,
+ &pd_std_efuse, NULL};
+
+static struct d_pwrd_info *vdd_iva_pds[] =
+{&pd_alwon_dsp, &pd_audio, &pd_ivahd, &pd_dsp, NULL};
+
+static struct d_pwrd_info *vdd_mpu_pds[] =
+{&pd_alwon_mpu, &pd_mpu, /* &pd_cpu0, &pd_cpu1, */ NULL};
+
+/* Voltage domains */
+
+#define N_VDDS 4
+
+struct d_vdd_info {
+ char *name;
+ int auto_ctrl_shift;
+ int auto_ctrl_mask;
+ struct d_pwrd_info **pds;
+};
+
+static struct d_vdd_info d_vdd[N_VDDS] = {
+ {
+ .name = "LDO_WAKEUP",
+ .auto_ctrl_shift = -1,
+ .auto_ctrl_mask = -1,
+ .pds = ldo_wakeup_pds,
+ },
+ {
+ .name = "VDD_CORE_L",
+ .auto_ctrl_shift = OMAP4430_AUTO_CTRL_VDD_CORE_L_SHIFT,
+ .auto_ctrl_mask = OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK,
+ .pds = vdd_core_pds,
+ },
+ {
+ .name = "VDD_IVA_L",
+ .auto_ctrl_shift = OMAP4430_AUTO_CTRL_VDD_IVA_L_SHIFT,
+ .auto_ctrl_mask = OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK,
+ .pds = vdd_iva_pds,
+ },
+ {
+ .name = "VDD_MPU_L",
+ .auto_ctrl_shift = OMAP4430_AUTO_CTRL_VDD_MPU_L_SHIFT,
+ .auto_ctrl_mask = OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK,
+ .pds = vdd_mpu_pds,
+ },
+};
+
+
+/* Display strings */
+
+static char *vddauto_s[] = {"disabled", "SLEEP", "RET", "reserved"};
+
+static char *pwrstate_s[] = {"OFF", "RET", "INACTIVE", "ON"};
+
+static char *logic_s[] = {"OFF", "ON"};
+
+static char *cmtrctrl_s[] = {"NOSLEEP", "SW_SLEEP", "SW_WKUP", "HW_AUTO"};
+
+static char *modmode_s[] = {"DISABLED", "AUTO", "ENABLED", "3"};
+
+static char *modstbyst_s[] = {"ON", "STBY"};
+
+static char *modidlest_s[] = {"ON", "TRANSITION", "IDLE", "DISABLED"};
+
+#if 0
+#define DEP_S_MAX 19
+
+static char *dep_s[DEP_S_MAX] = {"MPU_M3", "DSP", "IVAHD", "ABE", "MEMIF",
+ "L3_1", "L3_2", "L3INIT", "DSS", "ISS",
+ "GFX", "SDMA", "L4CFG", "L4PER", "L4SEC",
+ "L4WKUP", "ALWON_CORE", "STD_EFUSE",
+ "D2D"};
+#endif
+
+#define d_pr(sf, fmt, args...) \
+ { \
+ if (sf) \
+ seq_printf(sf, fmt , ## args); \
+ else \
+ pr_info(fmt , ## args); \
+ }
+
+#define d_pr_ctd(sf, fmt, args...) \
+ { \
+ if (sf) \
+ seq_printf(sf, fmt , ## args); \
+ else \
+ pr_cont(fmt , ## args); \
+ }
+
+static void prcmdebug_dump_dpll(struct seq_file *sf,
+ struct d_dpll_info *dpll,
+ int flags)
+{
+ u32 idlest = __raw_readl(dpll->idlestreg);
+ u32 st_bypass = idlest & OMAP4430_ST_MN_BYPASS_MASK;
+ u32 st_dpll_clk = idlest & OMAP4430_ST_DPLL_CLK_MASK;
+ struct d_dpll_derived **derived;
+
+ if (flags & (PRCMDEBUG_LASTSLEEP | PRCMDEBUG_ON) && !st_dpll_clk)
+ return;
+
+ d_pr(sf, " %s status=%s\n", dpll->name,
+ st_dpll_clk ? "locked" : st_bypass ? "bypass" : "stopped");
+
+ derived = dpll->derived;
+
+ while (*derived) {
+ u32 enabled = __raw_readl((*derived)->gatereg) &
+ (*derived)->gatemask;
+
+ if (!(flags & (PRCMDEBUG_LASTSLEEP | PRCMDEBUG_ON)) ||
+ enabled)
+ d_pr(sf, " %s enabled=0x%x\n",
+ (*derived)->name, enabled);
+ derived++;
+ }
+}
+
+
+static void prcmdebug_dump_intgen(struct seq_file *sf,
+ struct d_intgen_info *intgen,
+ int flags)
+{
+ u32 enabled = __raw_readl(intgen->gatereg) & intgen->gatemask;
+
+ if (flags & (PRCMDEBUG_LASTSLEEP | PRCMDEBUG_ON) && !enabled)
+ return;
+
+ d_pr(sf, " %s enabled=0x%x\n", intgen->name, enabled);
+}
+
+static void prcmdebug_dump_mod(struct seq_file *sf, struct d_mod_info *mod,
+ int flags)
+{
+ u32 clkctrl = __raw_readl(mod->clkctrl);
+ u32 stbyst = (clkctrl & OMAP4430_STBYST_MASK) >> OMAP4430_STBYST_SHIFT;
+ u32 idlest = (clkctrl & OMAP4430_IDLEST_MASK) >> OMAP4430_IDLEST_SHIFT;
+ u32 optclk = clkctrl & mod->optclk;
+
+ if (flags & (PRCMDEBUG_LASTSLEEP | PRCMDEBUG_ON) &&
+ (!(mod->flags & MOD_MASTER) || stbyst == 1) &&
+ (!(mod->flags & MOD_SLAVE) || idlest == 2 || idlest == 3) &&
+ !optclk)
+ return;
+
+ if (flags & PRCMDEBUG_LASTSLEEP &&
+ (mod->flags & MOD_MODE &&
+ ((clkctrl & OMAP4430_MODULEMODE_MASK) >>
+ OMAP4430_MODULEMODE_SHIFT) == 1 /* AUTO */) &&
+ (!(mod->flags & MOD_SLAVE) || idlest == 0) /* ON */ &&
+ !optclk)
+ return;
+
+ d_pr(sf, " %s", mod->name);
+
+ if (mod->flags & MOD_MODE)
+ d_pr_ctd(sf, " mode=%s",
+ modmode_s[(clkctrl & OMAP4430_MODULEMODE_MASK) >>
+ OMAP4430_MODULEMODE_SHIFT]);
+
+ if (mod->flags & MOD_MASTER)
+ d_pr_ctd(sf, " stbyst=%s",
+ modstbyst_s[stbyst]);
+
+ if (mod->flags & MOD_SLAVE)
+ d_pr_ctd(sf, " idlest=%s",
+ modidlest_s[idlest]);
+
+ if (optclk)
+ d_pr_ctd(sf, " optclk=0x%x", optclk);
+
+ d_pr_ctd(sf, "\n");
+}
+
+static void prcmdebug_dump_real_cd(struct seq_file *sf, struct d_clkd_info *cd,
+ int flags)
+{
+ u32 clktrctrl =
+ omap4_cminst_read_inst_reg(cd->prcm_partition, cd->cm_inst,
+ cd->clkdm_offs + OMAP4_CM_CLKSTCTRL);
+ u32 mode = (clktrctrl & OMAP4430_CLKTRCTRL_MASK) >>
+ OMAP4430_CLKTRCTRL_SHIFT;
+ u32 activity = clktrctrl & cd->activity;
+#if 0
+ u32 staticdep =
+ omap4_cminst_read_inst_reg(cd->prcm_partition, cd->cm_inst,
+ cd->clkdm_offs + OMAP4_CM_STATICDEP);
+ u32 dynamicdep =
+ omap4_cminst_read_inst_reg(cd->prcm_partition, cd->cm_inst,
+ cd->clkdm_offs +
+ OMAP4_CM_STATICDEP + 4) & 0xffffff;
+ int i;
+#endif
+
+ if (flags & PRCMDEBUG_LASTSLEEP && mode == 3 /* HW_AUTO */)
+ return;
+
+ d_pr(sf, " %s mode=%s", cd->name, cmtrctrl_s[mode]);
+
+ d_pr_ctd(sf, " activity=0x%x", activity);
+
+#if 0
+ if (staticdep) {
+ d_pr_ctd(sf, " static:");
+
+ for (i = 0; i < DEP_S_MAX; i++)
+ if (staticdep & (1 << i))
+ d_pr_ctd(sf, " %s", dep_s[i]);
+ }
+#endif
+
+#if 0
+ if (dynamicdep)
+ d_pr_ctd(sf, " dynamicdep=0x%x", dynamicdep);
+#endif
+
+ d_pr_ctd(sf, "\n");
+}
+
+static void prcmdebug_dump_cd(struct seq_file *sf, struct d_clkd_info *cd,
+ int flags)
+{
+ struct d_mod_info **mod;
+ struct d_intgen_info **intgen;
+ struct d_dpll_info **dpll;
+
+ if (cd->cm_inst != -1) {
+ prcmdebug_dump_real_cd(sf, cd, flags);
+ } else if (!(flags & PRCMDEBUG_LASTSLEEP)) {
+ d_pr(sf, " %s\n", cd->name);
+ }
+
+ mod = cd->mods;
+
+ while (*mod) {
+ prcmdebug_dump_mod(sf, *mod, flags);
+ mod++;
+ }
+
+ dpll = cd->dplls;
+
+ while (*dpll) {
+ prcmdebug_dump_dpll(sf, *dpll, flags);
+ dpll++;
+ }
+
+ intgen = cd->intgens;
+
+ while (*intgen) {
+ prcmdebug_dump_intgen(sf, *intgen, flags);
+ intgen++;
+ }
+}
+
+static void prcmdebug_dump_pd(struct seq_file *sf, struct d_pwrd_info *pd,
+ int flags)
+{
+ u32 pwrstst, currst, prevst;
+ struct d_clkd_info **cd;
+
+ if (pd->pwrst != -1 && pd->prminst != -1) {
+ pwrstst = omap4_prm_read_inst_reg(pd->prminst, pd->pwrst);
+ currst = (pwrstst & OMAP4430_POWERSTATEST_MASK) >>
+ OMAP4430_POWERSTATEST_SHIFT;
+ prevst = (pwrstst & OMAP4430_LASTPOWERSTATEENTERED_MASK) >>
+ OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
+
+ if (flags & PRCMDEBUG_LASTSLEEP &&
+ (prevst == PWRDM_POWER_OFF || prevst == PWRDM_POWER_RET))
+ return;
+
+ if (flags & PRCMDEBUG_ON &&
+ (currst == PWRDM_POWER_OFF || currst == PWRDM_POWER_RET))
+ return;
+
+ d_pr(sf, " %s curr=%s prev=%s logic=%s\n", pd->name,
+ pwrstate_s[currst],
+ pwrstate_s[prevst],
+ logic_s[(pwrstst & OMAP4430_LOGICSTATEST_MASK) >>
+ OMAP4430_LOGICSTATEST_SHIFT]);
+ } else {
+ if (flags & PRCMDEBUG_LASTSLEEP)
+ return;
+
+ d_pr(sf, " %s\n", pd->name);
+ }
+
+ cd = pd->cds;
+
+ while (*cd) {
+ prcmdebug_dump_cd(sf, *cd, flags);
+ cd++;
+ }
+}
+
+static int _prcmdebug_dump(struct seq_file *sf, int flags)
+{
+ int i;
+ u32 prm_voltctrl =
+ omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_VOLTCTRL_OFFSET);
+ struct d_pwrd_info **pd;
+
+ for (i = 0; i < N_VDDS; i++) {
+ if (!(flags & PRCMDEBUG_LASTSLEEP)) {
+ d_pr(sf, "%s",
+ d_vdd[i].name);
+
+ if (d_vdd[i].auto_ctrl_shift != -1) {
+ int auto_ctrl =
+ (prm_voltctrl &
+ d_vdd[i].auto_ctrl_mask) >>
+ d_vdd[i].auto_ctrl_shift;
+ d_pr_ctd(sf, " auto=%s\n",
+ vddauto_s[auto_ctrl]);
+ } else {
+ d_pr_ctd(sf, " (no auto)\n");
+ }
+
+ }
+
+ pd = d_vdd[i].pds;
+
+ while (*pd) {
+ prcmdebug_dump_pd(sf, *pd, flags);
+ pd++;
+ }
+ }
+
+ return 0;
+}
+
+void prcmdebug_dump(int flags)
+{
+ _prcmdebug_dump(NULL, flags);
+}
+
+static int prcmdebug_all_dump(struct seq_file *sf, void *private)
+{
+ _prcmdebug_dump(sf, 0);
+ return 0;
+}
+
+static int prcmdebug_all_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, prcmdebug_all_dump, NULL);
+}
+
+
+static struct file_operations prcmdebug_all_fops = {
+ .open = prcmdebug_all_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int prcmdebug_on_dump(struct seq_file *sf, void *private)
+{
+ _prcmdebug_dump(sf, PRCMDEBUG_ON);
+ return 0;
+}
+
+static int prcmdebug_on_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, prcmdebug_on_dump, NULL);
+}
+
+static struct file_operations prcmdebug_on_fops = {
+ .open = prcmdebug_on_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init prcmdebug_init(void)
+{
+ if (IS_ERR_OR_NULL(debugfs_create_file("prcm", S_IRUGO, NULL, NULL,
+ &prcmdebug_all_fops)))
+ pr_err("%s: failed to create prcm file\n", __func__);
+
+ if (IS_ERR_OR_NULL(debugfs_create_file("prcm-on", S_IRUGO, NULL, NULL,
+ &prcmdebug_on_fops)))
+ pr_err("%s: failed to create prcm-on file\n", __func__);
+
+ return 0;
+}
+
+arch_initcall(prcmdebug_init);
diff --git a/arch/arm/mach-omap2/prcm-debug.h b/arch/arm/mach-omap2/prcm-debug.h
new file mode 100644
index 0000000..14ca00fb
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm-debug.h
@@ -0,0 +1,13 @@
+#ifndef __ARCH_ASM_MACH_OMAP2_PRCM_DEBUG_H
+#define __ARCH_ASM_MACH_OMAP2_PRCM_DEBUG_H
+
+#define PRCMDEBUG_LASTSLEEP (1 << 0)
+#define PRCMDEBUG_ON (1 << 1)
+
+#ifdef CONFIG_PM_DEBUG
+extern void prcmdebug_dump(int flags);
+#else
+static inline void prcmdebug_dump(int flags) { }
+#endif
+
+#endif /* __ARCH_ASM_MACH_OMAP2_PRCM_DEBUG_H */
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 64c087a..c38c459 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -216,6 +216,7 @@
/* PRM_SYSCONFIG specific bits */
/* PRM_IRQSTATUS_MPU specific bits */
+#define OMAP3630_ABB_LDO_TRANXDONE_ST_MASK (1 << 26)
#define OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT 25
#define OMAP3430ES2_SND_PERIPH_DPLL_ST_MASK (1 << 25)
#define OMAP3430_VC_TIMEOUTERR_ST_MASK (1 << 24)
diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h
index 6d2776f..b76cfd6 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)
@@ -92,6 +92,10 @@
#define OMAP4430_AUTO_CTRL_VDD_MPU_L_SHIFT 2
#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK (0x3 << 2)
+/* Used by PRM_VOLTCTRL */
+#define OMAP4430_AUTO_CTRL_VDD_RET_MASK (1 << 1)
+#define OMAP4430_AUTO_CTRL_VDD_SLEEP_MASK (1 << 0)
+
/* Used by PRM_VC_ERRST */
#define OMAP4430_BYPS_RA_ERR_SHIFT 25
#define OMAP4430_BYPS_RA_ERR_MASK (1 << 25)
@@ -283,6 +287,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)
@@ -390,6 +402,8 @@
/* Used by PRM_IO_PMCTRL */
#define OMAP4430_GLOBAL_WUEN_SHIFT 16
#define OMAP4430_GLOBAL_WUEN_MASK (1 << 16)
+#define OMAP4430_ISOOVR_EXTEND_SHIFT 4
+#define OMAP4430_ISOOVR_EXTEND_MASK (1 << 4)
/* Used by PRM_VC_CFG_I2C_MODE */
#define OMAP4430_HSMCODE_SHIFT 0
@@ -1063,6 +1077,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..49e9719 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,80 @@ 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_prm_irq - OMAP3 PRM IRQ register access description.
+ * @vp_tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ * @abb_tranxdone_status: ABB_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ * (ONLY for OMAP3630)
+ */
+struct omap3_prm_irq {
+ u32 vp_tranxdone_status;
+ u32 abb_tranxdone_status;
+};
+
+static struct omap3_prm_irq omap3_prm_irqs[] = {
+ [OMAP3_PRM_IRQ_VDD_MPU_ID] = {
+ .vp_tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+ .abb_tranxdone_status = OMAP3630_ABB_LDO_TRANXDONE_ST_MASK,
+ },
+ [OMAP3_PRM_IRQ_VDD_CORE_ID] = {
+ .vp_tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+ /* no abb for core */
+ },
+};
+
+#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
+
+u32 omap3_prm_vp_check_txdone(u8 irq_id)
+{
+ struct omap3_prm_irq *irq = &omap3_prm_irqs[irq_id];
+ u32 irqstatus;
+
+ irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+ return irqstatus & irq->vp_tranxdone_status;
+}
+
+void omap3_prm_vp_clear_txdone(u8 irq_id)
+{
+ struct omap3_prm_irq *irq = &omap3_prm_irqs[irq_id];
+
+ omap2_prm_write_mod_reg(irq->vp_tranxdone_status,
+ OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+u32 omap36xx_prm_abb_check_txdone(u8 irq_id)
+{
+ struct omap3_prm_irq *irq = &omap3_prm_irqs[irq_id];
+ u32 irqstatus;
+
+ irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+ return irqstatus & irq->abb_tranxdone_status;
+}
+
+void omap36xx_prm_abb_clear_txdone(u8 irq_id)
+{
+ struct omap3_prm_irq *irq = &omap3_prm_irqs[irq_id];
+
+ omap2_prm_write_mod_reg(irq->abb_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..08d5f1e 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -167,6 +167,10 @@
#define OMAP3430_PRM_VP2_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
#define OMAP3_PRM_VP2_STATUS_OFFSET 0x00e4
#define OMAP3430_PRM_VP2_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
+#define OMAP3_PRM_LDO_ABB_SETUP_OFFSET 0x00f0
+#define OMAP3630_PRM_LDO_ABB_SETUP OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00f0)
+#define OMAP3_PRM_LDO_ABB_CTRL_OFFSET 0x00f4
+#define OMAP3630_PRM_LDO_ABB_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00f4)
#define OMAP3_PRM_CLKSEL_OFFSET 0x0040
#define OMAP3430_PRM_CLKSEL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
@@ -303,7 +307,25 @@ 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);
+#define OMAP3_PRM_IRQ_VDD_MPU_ID 0
+#define OMAP3_PRM_IRQ_VDD_CORE_ID 1
+/* OMAP3-specific VP functions */
+u32 omap3_prm_vp_check_txdone(u8 irq_id);
+void omap3_prm_vp_clear_txdone(u8 irq_id);
+
+/* OMAP36xx-specific ABB functions */
+u32 omap36xx_prm_abb_check_txdone(u8 irq_id);
+void omap36xx_prm_abb_clear_txdone(u8 irq_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..6f011e0 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -21,8 +21,12 @@
#include <plat/cpu.h>
#include <plat/prcm.h>
+#include "voltage.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 +197,112 @@ void omap4_prm_global_warm_sw_reset(void)
v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
OMAP4_RM_RSTCTRL);
}
+
+void omap4_prm_global_cold_sw_reset(void)
+{
+ u32 v;
+
+ v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ OMAP4_RM_RSTCTRL);
+ v |= OMAP4430_RST_GLOBAL_COLD_SW_MASK;
+ omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
+ OMAP4_RM_RSTCTRL);
+
+ /* OCP barrier */
+ v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ OMAP4_RM_RSTCTRL);
+}
+
+/* PRM VP */
+
+/*
+ * struct omap4_prm_irq - OMAP4 VP register access description.
+ * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
+ * @vp_tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ * @abb_tranxdone_status: ABB_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap4_prm_irq {
+ u32 irqstatus_mpu;
+ u32 vp_tranxdone_status;
+ u32 abb_tranxdone_status;
+};
+
+static struct omap4_prm_irq omap4_prm_irqs[] = {
+ [OMAP4_PRM_IRQ_VDD_MPU_ID] = {
+ .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+ .vp_tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+ .abb_tranxdone_status = OMAP4430_ABB_MPU_DONE_ST_MASK
+ },
+ [OMAP4_PRM_IRQ_VDD_IVA_ID] = {
+ .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+ .vp_tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+ .abb_tranxdone_status = OMAP4430_ABB_IVA_DONE_ST_MASK,
+ },
+ [OMAP4_PRM_IRQ_VDD_CORE_ID] = {
+ .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+ .vp_tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+ /* Core has no ABB */
+ },
+};
+
+u32 omap4_prm_vp_check_txdone(u8 irq_id)
+{
+ struct omap4_prm_irq *irq = &omap4_prm_irqs[irq_id];
+ u32 irqstatus;
+
+ irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ irq->irqstatus_mpu);
+ return irqstatus & irq->vp_tranxdone_status;
+}
+
+void omap4_prm_vp_clear_txdone(u8 irq_id)
+{
+ struct omap4_prm_irq *irq = &omap4_prm_irqs[irq_id];
+
+ omap4_prminst_write_inst_reg(irq->vp_tranxdone_status,
+ OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ irq->irqstatus_mpu);
+};
+
+u32 omap4_prm_abb_check_txdone(u8 irq_id)
+{
+ struct omap4_prm_irq *irq = &omap4_prm_irqs[irq_id];
+ u32 irqstatus;
+
+ irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ irq->irqstatus_mpu);
+ return irqstatus & irq->abb_tranxdone_status;
+}
+
+void omap4_prm_abb_clear_txdone(u8 irq_id)
+{
+ struct omap4_prm_irq *irq = &omap4_prm_irqs[irq_id];
+
+ omap4_prminst_write_inst_reg(irq->abb_tranxdone_status,
+ OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ irq->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..ead36e1 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
@@ -772,6 +772,25 @@ extern int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
extern int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
extern void omap4_prm_global_warm_sw_reset(void);
+extern void omap4_prm_global_cold_sw_reset(void);
+
+#define OMAP4_PRM_IRQ_VDD_CORE_ID 0
+#define OMAP4_PRM_IRQ_VDD_IVA_ID 1
+#define OMAP4_PRM_IRQ_VDD_MPU_ID 2
+/* OMAP4-specific VP functions */
+u32 omap4_prm_vp_check_txdone(u8 irq_id);
+void omap4_prm_vp_clear_txdone(u8 irq_id);
+/* OMAP4-specific ABB functions */
+u32 omap4_prm_abb_check_txdone(u8 irq_id);
+void omap4_prm_abb_clear_txdone(u8 irq_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
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index a303242..b6a286f 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -22,13 +22,14 @@
#include "prm-regbits-44xx.h"
#include "prcm44xx.h"
#include "prcm_mpu44xx.h"
+#include "scrm44xx.h"
static u32 _prm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
[OMAP4430_INVALID_PRCM_PARTITION] = 0,
[OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE,
[OMAP4430_CM1_PARTITION] = 0,
[OMAP4430_CM2_PARTITION] = 0,
- [OMAP4430_SCRM_PARTITION] = 0,
+ [OMAP4430_SCRM_PARTITION] = OMAP4_SCRM_BASE,
[OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE,
};
diff --git a/arch/arm/mach-omap2/remoteproc.c b/arch/arm/mach-omap2/remoteproc.c
new file mode 100644
index 0000000..b8ae36f
--- /dev/null
+++ b/arch/arm/mach-omap2/remoteproc.c
@@ -0,0 +1,164 @@
+/*
+ * 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/slab.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>
+#include "cm2_44xx.h"
+#include "cm-regbits-44xx.h"
+
+#define OMAP4430_CM_M3_M3_CLKCTRL (OMAP4430_CM2_BASE + OMAP4430_CM2_CORE_INST \
+ + OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET)
+
+static struct omap_rproc_timers_info ipu_timers[] = {
+ { .id = 3 },
+ { .id = 4 },
+#ifdef CONFIG_REMOTEPROC_WATCHDOG
+ { .id = 9 },
+ { .id = 11 },
+#endif
+};
+
+static struct omap_rproc_pdata omap4_rproc_data[] = {
+ {
+ .name = "dsp",
+ .iommu_name = "tesla",
+ .firmware = "tesla-dsp.bin",
+ .oh_name = "dsp_c0",
+ .clkdm_name = "dsp_clkdm",
+ },
+ {
+ .name = "ipu",
+ .iommu_name = "ducati",
+ .firmware = "ducati-m3.bin",
+ .oh_name = "ipu_c0",
+ .oh_name_opt = "ipu_c1",
+ .clkdm_name = "ducati_clkdm",
+ .timers = ipu_timers,
+ .timers_cnt = ARRAY_SIZE(ipu_timers),
+ .idle_addr = OMAP4430_CM_M3_M3_CLKCTRL,
+ .idle_mask = OMAP4430_STBYST_MASK,
+ .suspend_addr = 0xb3bf02d8,
+ .suspend_mask = ~0,
+ .sus_timeout = 5000,
+ .sus_mbox_name = "mailbox-1",
+ },
+};
+
+static struct omap_device_pm_latency omap_rproc_latency[] = {
+ {
+ OMAP_RPROC_DEFAULT_PM_LATENCY,
+ },
+};
+
+static struct rproc_mem_pool *omap_rproc_get_pool(const char *name)
+{
+ struct rproc_mem_pool *pool = NULL;
+
+ /* check for ipu currently. dsp will be handled later */
+ if (!strcmp("ipu", name)) {
+ phys_addr_t paddr1 = omap_ipu_get_mempool_base(
+ OMAP_RPROC_MEMPOOL_STATIC);
+ phys_addr_t paddr2 = omap_ipu_get_mempool_base(
+ OMAP_RPROC_MEMPOOL_DYNAMIC);
+ u32 len1 = omap_ipu_get_mempool_size(OMAP_RPROC_MEMPOOL_STATIC);
+ u32 len2 = omap_ipu_get_mempool_size(OMAP_RPROC_MEMPOOL_DYNAMIC);
+
+ if (!paddr1 && !paddr2) {
+ pr_err("no carveout memory available at all for "
+ "remotproc\n");
+ return pool;
+ }
+ if (!paddr1 || !len1)
+ pr_warn("static memory is unavailable: 0x%x, 0x%x\n",
+ paddr1, len1);
+ if (!paddr2 || !len2)
+ pr_warn("carveout memory is unavailable: 0x%x, 0x%x\n",
+ paddr2, len2);
+
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+ if (pool) {
+ pool->st_base = paddr1;
+ pool->st_size = len1;
+ pool->mem_base = paddr2;
+ pool->mem_size = len2;
+ pool->cur_base = paddr2;
+ pool->cur_size = len2;
+ }
+ }
+
+ return pool;
+}
+
+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;
+
+ /* names like ipu_cx/dsp_cx might show up on other OMAPs, too */
+ if (!cpu_is_omap44xx())
+ return 0;
+
+ 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++;
+ }
+
+ omap4_rproc_data[i].memory_pool =
+ omap_rproc_get_pool(omap4_rproc_data[i].name);
+ 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/resetreason.c b/arch/arm/mach-omap2/resetreason.c
new file mode 100644
index 0000000..316bfeb
--- /dev/null
+++ b/arch/arm/mach-omap2/resetreason.c
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-omap2/resetreason.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prm44xx.h"
+#include "prminst44xx.h"
+#include "resetreason.h"
+
+static char resetreason[1024];
+
+static struct {
+ const char *str;
+ u32 mask;
+} resetreason_flags[] = {
+ { "C2C ", OMAP4430_C2C_RST_MASK },
+ { "IcePick ", OMAP4430_ICEPICK_RST_MASK },
+ { "Voltage Manager ", OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK |
+ OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK |
+ OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK },
+ { "external warm ", OMAP4430_EXTERNAL_WARM_RST_MASK },
+ { "MPU Watchdog Timer ", OMAP4430_MPU_WDT_RST_MASK },
+ { "warm software ", OMAP4430_GLOBAL_WARM_SW_RST_MASK },
+ { "cold ", OMAP4430_GLOBAL_COLD_RST_MASK },
+};
+
+const char *omap4_get_resetreason(void)
+{
+ return resetreason;
+}
+
+static int __init resetreason_init(void)
+{
+ int i;
+ u32 reasons =
+ omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ OMAP4_PRM_RSTST_OFFSET);
+ char buf[128];
+
+ strlcpy(resetreason, "Last reset was ", sizeof(resetreason));
+
+ for (i = 0; i < ARRAY_SIZE(resetreason_flags); i++)
+ if (reasons & resetreason_flags[i].mask)
+ strlcat(resetreason, resetreason_flags[i].str,
+ sizeof(resetreason));
+
+ snprintf(buf, sizeof(buf), "reset (PRM_RSTST=0x%x)\n", reasons);
+
+ strlcat(resetreason, buf, sizeof(resetreason));
+
+ pr_info("%s\n", resetreason);
+
+ omap4_prminst_write_inst_reg(reasons, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_RSTST_OFFSET);
+
+ return 0;
+}
+
+postcore_initcall(resetreason_init);
diff --git a/arch/arm/mach-omap2/resetreason.h b/arch/arm/mach-omap2/resetreason.h
new file mode 100644
index 0000000..96c9a00
--- /dev/null
+++ b/arch/arm/mach-omap2/resetreason.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-omap2/resetreason.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MACH_OMAP2_RESETREASON_H_
+#define _MACH_OMAP2_RESETREASON_H_
+
+const char *omap4_get_resetreason(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1ac361b..76b9cfb 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -19,26 +19,20 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/serial_reg.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/serial_8250.h>
#include <linux/pm_runtime.h>
-#include <linux/console.h>
-#ifdef CONFIG_SERIAL_OMAP
#include <plat/omap-serial.h>
-#endif
-
#include <plat/common.h>
#include <plat/board.h>
#include <plat/clock.h>
#include <plat/dma.h>
-#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
#include "prm2xxx_3xxx.h"
#include "pm.h"
@@ -47,65 +41,19 @@
#include "control.h"
#include "mux.h"
-#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52
-#define UART_OMAP_WER 0x17 /* Wake-up enable register */
-
-#define UART_ERRATA_FIFO_FULL_ABORT (0x1 << 0)
-#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
-
-/*
- * 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.
- */
-#define DEFAULT_TIMEOUT 0
-
#define MAX_UART_HWMOD_NAME_LEN 16
-struct omap_uart_state {
- int num;
- int can_sleep;
- struct timer_list timer;
- u32 timeout;
-
- void __iomem *wk_st;
- void __iomem *wk_en;
- u32 wk_mask;
- u32 padconf;
- u32 dma_enabled;
-
- struct clk *ick;
- struct clk *fck;
- int clocked;
-
- int irq;
- int regshift;
- int irqflags;
- void __iomem *membase;
- resource_size_t mapbase;
-
- struct list_head node;
- struct omap_hwmod *oh;
- struct platform_device *pdev;
-
- u32 errata;
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
- int context_valid;
-
- /* Registers to be saved/restored for OFF-mode */
- u16 dll;
- u16 dlh;
- u16 ier;
- u16 sysc;
- u16 scr;
- u16 wer;
- u16 mcr;
-#endif
-};
+static int omap_uart_con_id __initdata = -1;
-static LIST_HEAD(uart_list);
-static u8 num_uarts;
+static struct omap_uart_port_info omap_serial_default_info[] = {
+ {
+ .use_dma = 0,
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .auto_sus_timeout = DEFAULT_AUTOSUSPEND_DELAY,
+ },
+};
static int uart_idle_hwmod(struct omap_device *od)
{
@@ -129,396 +77,203 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
},
};
-static inline unsigned int __serial_read_reg(struct uart_port *up,
- int offset)
-{
- offset <<= up->regshift;
- return (unsigned int)__raw_readb(up->membase + offset);
-}
-
-static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
- int offset)
-{
- offset <<= uart->regshift;
- return (unsigned int)__raw_readb(uart->membase + offset);
-}
-
-static inline void __serial_write_reg(struct uart_port *up, int offset,
- int value)
-{
- offset <<= up->regshift;
- __raw_writeb(value, up->membase + offset);
-}
-
-static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
- int value)
-{
- offset <<= uart->regshift;
- __raw_writeb(value, uart->membase + offset);
-}
-
-/*
- * Internal UARTs need to be initialized for the 8250 autoconfig to work
- * properly. Note that the TX watermark initialization may not be needed
- * once the 8250.c watermark handling code is merged.
- */
-
-static inline void __init omap_uart_reset(struct omap_uart_state *uart)
-{
- serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
- serial_write_reg(uart, UART_OMAP_SCR, 0x08);
- serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
-}
-
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
-
-/*
- * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
- * The access to uart register after MDR1 Access
- * causes UART to corrupt data.
- *
- * Need a delay =
- * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
- * give 10 times as much
- */
-static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
- u8 fcr_val)
-{
- u8 timeout = 255;
-
- serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
- udelay(2);
- serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
- UART_FCR_CLEAR_RCVR);
- /*
- * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
- * TX_FIFO_E bit is 1.
- */
- while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
- (UART_LSR_THRE | UART_LSR_DR))) {
- timeout--;
- if (!timeout) {
- /* Should *never* happen. we warn and carry on */
- dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
- serial_read_reg(uart, UART_LSR));
- break;
- }
- udelay(1);
- }
-}
-
-static void omap_uart_save_context(struct omap_uart_state *uart)
-{
- u16 lcr = 0;
-
- if (!enable_off_mode)
- return;
-
- lcr = serial_read_reg(uart, UART_LCR);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- uart->dll = serial_read_reg(uart, UART_DLL);
- uart->dlh = serial_read_reg(uart, UART_DLM);
- serial_write_reg(uart, UART_LCR, lcr);
- uart->ier = serial_read_reg(uart, UART_IER);
- uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
- uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
- uart->wer = serial_read_reg(uart, UART_OMAP_WER);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
- uart->mcr = serial_read_reg(uart, UART_MCR);
- serial_write_reg(uart, UART_LCR, lcr);
-
- uart->context_valid = 1;
-}
-
-static void omap_uart_restore_context(struct omap_uart_state *uart)
-{
- u16 efr = 0;
+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_uart1_pads[] __initdata = {
+ {
+ .name = "uart1_cts.uart1_cts",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart1_rts.uart1_rts",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart1_tx.uart1_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart1_rx.uart1_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+};
- if (!enable_off_mode)
- return;
+static struct omap_device_pad default_uart2_pads[] __initdata = {
+ {
+ .name = "uart2_cts.uart2_cts",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_rts.uart2_rts",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_tx.uart2_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_rx.uart2_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+};
- if (!uart->context_valid)
- return;
+static struct omap_device_pad default_uart3_pads[] __initdata = {
+ {
+ .name = "uart3_cts_rctx.uart3_cts_rctx",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_rts_sd.uart3_rts_sd",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_tx_irtx.uart3_tx_irtx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_rx_irrx.uart3_rx_irrx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ },
+};
- uart->context_valid = 0;
+static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {
+ {
+ .name = "gpmc_wait2.uart4_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "gpmc_wait3.uart4_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
+ },
+};
- if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
- omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
- else
- serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
-
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- efr = serial_read_reg(uart, UART_EFR);
- serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
- serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
- serial_write_reg(uart, UART_IER, 0x0);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_write_reg(uart, UART_DLL, uart->dll);
- serial_write_reg(uart, UART_DLM, uart->dlh);
- serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
- serial_write_reg(uart, UART_IER, uart->ier);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_write_reg(uart, UART_MCR, uart->mcr);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_write_reg(uart, UART_EFR, efr);
- serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
- serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
- serial_write_reg(uart, UART_OMAP_WER, uart->wer);
- serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
-
- if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
- omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
- else
- /* UART 16x mode */
- serial_write_reg(uart, UART_OMAP_MDR1,
- UART_OMAP_MDR1_16X_MODE);
-}
+static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {
+ {
+ .name = "uart4_tx.uart4_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart4_rx.uart4_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ },
+};
#else
-static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
-static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
-#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
-
-static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
-{
- if (uart->clocked)
- return;
-
- omap_device_enable(uart->pdev);
- uart->clocked = 1;
- omap_uart_restore_context(uart);
-}
-
-#ifdef CONFIG_PM
-
-static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
-{
- if (!uart->clocked)
- return;
-
- omap_uart_save_context(uart);
- uart->clocked = 0;
- omap_device_idle(uart->pdev);
-}
-
-static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
-{
- /* Set wake-enable bit */
- if (uart->wk_en && uart->wk_mask) {
- u32 v = __raw_readl(uart->wk_en);
- v |= uart->wk_mask;
- __raw_writel(v, uart->wk_en);
- }
-
- /* Ensure IOPAD wake-enables are set */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 v = omap_ctrl_readw(uart->padconf);
- v |= OMAP3_PADCONF_WAKEUPENABLE0;
- omap_ctrl_writew(v, uart->padconf);
- }
-}
-
-static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
-{
- /* Clear wake-enable bit */
- if (uart->wk_en && uart->wk_mask) {
- u32 v = __raw_readl(uart->wk_en);
- v &= ~uart->wk_mask;
- __raw_writel(v, uart->wk_en);
- }
-
- /* Ensure IOPAD wake-enables are cleared */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 v = omap_ctrl_readw(uart->padconf);
- v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
- omap_ctrl_writew(v, uart->padconf);
- }
-}
-
-static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
- int enable)
-{
- u8 idlemode;
-
- if (enable) {
- /**
- * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
- * in Smartidle Mode When Configured for DMA Operations.
- */
- if (uart->dma_enabled)
- idlemode = HWMOD_IDLEMODE_FORCE;
- else
- idlemode = HWMOD_IDLEMODE_SMART;
- } else {
- idlemode = HWMOD_IDLEMODE_NO;
- }
-
- omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
-}
-
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
-{
- omap_uart_enable_clocks(uart);
-
- omap_uart_smart_idle_enable(uart, 0);
- uart->can_sleep = 0;
- if (uart->timeout)
- mod_timer(&uart->timer, jiffies + uart->timeout);
- else
- del_timer(&uart->timer);
-}
-
-static void omap_uart_allow_sleep(struct omap_uart_state *uart)
-{
- if (device_may_wakeup(&uart->pdev->dev))
- omap_uart_enable_wakeup(uart);
- else
- omap_uart_disable_wakeup(uart);
-
- if (!uart->clocked)
- return;
-
- omap_uart_smart_idle_enable(uart, 1);
- uart->can_sleep = 1;
- del_timer(&uart->timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
- struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
- omap_uart_allow_sleep(uart);
-}
-
-void omap_uart_prepare_idle(int num)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (num == uart->num && uart->can_sleep) {
- omap_uart_disable_clocks(uart);
- return;
- }
- }
-}
-
-void omap_uart_resume_idle(int num)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (num == uart->num && uart->can_sleep) {
- omap_uart_enable_clocks(uart);
-
- /* Check for IO pad wakeup */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 p = omap_ctrl_readw(uart->padconf);
-
- if (p & OMAP3_PADCONF_WAKEUPEVENT0)
- omap_uart_block_sleep(uart);
- }
+static struct omap_device_pad default_uart1_pads[] __initdata = {};
+static struct omap_device_pad default_uart2_pads[] __initdata = {};
+static struct omap_device_pad default_uart3_pads[] __initdata = {};
+static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {};
+static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {};
+#endif
- /* Check for normal UART wakeup */
- if (__raw_readl(uart->wk_st) & uart->wk_mask)
- omap_uart_block_sleep(uart);
- return;
+static __init void omap_serial_fill_default_pads(struct omap_board_data *bdata)
+{
+ BUG_ON(!cpu_is_omap44xx() && !cpu_is_omap34xx());
+
+ switch (bdata->id) {
+ case 0:
+ bdata->pads = default_uart1_pads;
+ bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads);
+ break;
+ case 1:
+ bdata->pads = default_uart2_pads;
+ bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads);
+ break;
+ case 2:
+ bdata->pads = default_uart3_pads;
+ bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads);
+ break;
+ case 3:
+ if (cpu_is_omap44xx()) {
+ bdata->pads = default_omap4_uart4_pads;
+ bdata->pads_cnt =
+ ARRAY_SIZE(default_omap4_uart4_pads);
+ } else {
+ bdata->pads = default_omap36xx_uart4_pads;
+ bdata->pads_cnt =
+ ARRAY_SIZE(default_omap36xx_uart4_pads);
}
+ break;
+ default:
+ break;
}
}
-void omap_uart_prepare_suspend(void)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- omap_uart_allow_sleep(uart);
- }
-}
-
-int omap_uart_can_sleep(void)
+/* TBD: Will be removed once we have irq-chaing mechanism */
+static bool omap_uart_chk_wakeup(struct platform_device *pdev)
{
- struct omap_uart_state *uart;
- int can_sleep = 1;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (!uart->clocked)
- continue;
-
- if (!uart->can_sleep) {
- can_sleep = 0;
- continue;
+ struct omap_uart_port_info *up = pdev->dev.platform_data;
+ struct omap_device *od;
+ u32 wkst = 0;
+ bool ret = false;
+
+ od = to_omap_device(pdev);
+ if (omap_hwmod_pad_get_wakeup_status(od->hwmods[0]))
+ ret = true;
+
+ if (up->wk_st && up->wk_en && up->wk_mask) {
+ /* Check for normal UART wakeup (and clear it) */
+ wkst = __raw_readl(up->wk_st) & up->wk_mask;
+ if (wkst) {
+ __raw_writel(wkst, up->wk_st);
+ ret = true;
}
-
- /* This UART can now safely sleep. */
- omap_uart_allow_sleep(uart);
}
- return can_sleep;
+ return ret;
}
-/**
- * omap_uart_interrupt()
- *
- * This handler is used only to detect that *any* UART interrupt has
- * occurred. It does _nothing_ to handle the interrupt. Rather,
- * any UART interrupt will trigger the inactivity timer so the
- * UART will not idle or sleep for its timeout period.
- *
- **/
-/* static int first_interrupt; */
-static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
+static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable)
{
- struct omap_uart_state *uart = dev_id;
-
- omap_uart_block_sleep(uart);
+ struct omap_device *od;
- return IRQ_NONE;
+ od = to_omap_device(pdev);
+ if (enable)
+ omap_hwmod_enable_wakeup(od->hwmods[0]);
+ else
+ omap_hwmod_disable_wakeup(od->hwmods[0]);
}
-static void omap_uart_idle_init(struct omap_uart_state *uart)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+ unsigned short num)
{
- int ret;
-
- uart->can_sleep = 0;
- uart->timeout = DEFAULT_TIMEOUT;
- setup_timer(&uart->timer, omap_uart_idle_timer,
- (unsigned long) uart);
- if (uart->timeout)
- mod_timer(&uart->timer, jiffies + uart->timeout);
- omap_uart_smart_idle_enable(uart, 0);
-
- if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
- u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+ if (cpu_is_omap44xx()) {
+ uart->wer |= OMAP4_UART_WER_MOD_WKUP;
+ } else if (cpu_is_omap34xx()) {
+ u32 mod = num > 1 ? OMAP3430_PER_MOD : CORE_MOD;
u32 wk_mask = 0;
- u32 padconf = 0;
- /* XXX These PRM accesses do not belong here */
+ uart->wer |= OMAP2_UART_WER_MOD_WKUP;
uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
- switch (uart->num) {
+ switch (num) {
case 0:
wk_mask = OMAP3430_ST_UART1_MASK;
- padconf = 0x182;
break;
case 1:
wk_mask = OMAP3430_ST_UART2_MASK;
- padconf = 0x17a;
break;
case 2:
wk_mask = OMAP3430_ST_UART3_MASK;
- padconf = 0x19e;
break;
case 3:
wk_mask = OMAP3630_ST_UART4_MASK;
- padconf = 0x0d2;
break;
}
uart->wk_mask = wk_mask;
- uart->padconf = padconf;
} else if (cpu_is_omap24xx()) {
u32 wk_mask = 0;
u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
- switch (uart->num) {
+ switch (num) {
case 0:
wk_mask = OMAP24XX_ST_UART1_MASK;
break;
@@ -543,162 +298,87 @@ 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;
- }
-
- uart->irqflags |= IRQF_SHARED;
- ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
- IRQF_SHARED, "serial idle", (void *)uart);
- WARN_ON(ret);
-}
-
-void omap_uart_enable_irqs(int enable)
-{
- int ret;
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (enable) {
- pm_runtime_put_sync(&uart->pdev->dev);
- ret = request_threaded_irq(uart->irq, NULL,
- omap_uart_interrupt,
- IRQF_SHARED,
- "serial idle",
- (void *)uart);
- } else {
- pm_runtime_get_noresume(&uart->pdev->dev);
- free_irq(uart->irq, (void *)uart);
- }
}
}
-static ssize_t sleep_timeout_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+char *cmdline_find_option(char *str)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_device *odev = to_omap_device(pdev);
- struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
+ extern char *saved_command_line;
- return sprintf(buf, "%u\n", uart->timeout / HZ);
+ return strstr(saved_command_line, str);
}
-static ssize_t sleep_timeout_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t n)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_device *odev = to_omap_device(pdev);
- struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
- unsigned int value;
-
- if (sscanf(buf, "%u", &value) != 1) {
- dev_err(dev, "sleep_timeout_store: Invalid value\n");
- return -EINVAL;
- }
-
- uart->timeout = value * HZ;
- if (uart->timeout)
- mod_timer(&uart->timer, jiffies + uart->timeout);
- else
- /* A zero value means disable timeout feature */
- omap_uart_block_sleep(uart);
-
- return n;
-}
+ struct omap_hwmod *oh;
+ char oh_name[MAX_UART_HWMOD_NAME_LEN];
-static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
- sleep_timeout_store);
-#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
-#else
-static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
-{
- /* Needed to enable UART clocks when built without CONFIG_PM */
- omap_uart_enable_clocks(uart);
+ snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1);
+ oh = omap_hwmod_lookup(oh_name);
+ WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n",
+ oh_name);
+ return oh;
}
-#define DEV_CREATE_FILE(dev, attr)
-#endif /* CONFIG_PM */
-#ifndef CONFIG_SERIAL_OMAP
-/*
- * Override the default 8250 read handler: mem_serial_in()
- * Empty RX fifo read causes an abort on omap3630 and omap4
- * This function makes sure that an empty rx fifo is not read on these silicons
- * (OMAP1/2/3430 are not affected)
- */
-static unsigned int serial_in_override(struct uart_port *up, int offset)
+void omap_rts_mux_write(u16 val, int num)
{
- if (UART_RX == offset) {
- unsigned int lsr;
- lsr = __serial_read_reg(up, UART_LSR);
- if (!(lsr & UART_LSR_DR))
- return -EPERM;
- }
-
- return __serial_read_reg(up, offset);
-}
+ struct omap_hwmod *oh;
+ int i;
-static void serial_out_override(struct uart_port *up, int offset, int value)
-{
- unsigned int status, tmout = 10000;
+ oh = omap_uart_hwmod_lookup(num);
+ if (!oh)
+ return;
- status = __serial_read_reg(up, UART_LSR);
- while (!(status & UART_LSR_THRE)) {
- /* Wait up to 10ms for the character(s) to be sent. */
- if (--tmout == 0)
+ for (i = 0; i < oh->mux->nr_pads ; i++) {
+ if (strstr(oh->mux->pads[i].name, "rts")) {
+ omap_mux_write(oh->mux->pads[i].partition,
+ val,
+ oh->mux->pads[i].mux[0].reg_offset);
break;
- udelay(1);
- status = __serial_read_reg(up, UART_LSR);
+ }
}
- __serial_write_reg(up, offset, value);
}
-#endif
static int __init omap_serial_early_init(void)
{
int i = 0;
+ char omap_tty_name[MAX_UART_HWMOD_NAME_LEN];
+ struct omap_hwmod *oh;
- do {
- char oh_name[MAX_UART_HWMOD_NAME_LEN];
- struct omap_hwmod *oh;
- struct omap_uart_state *uart;
-
- snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
- "uart%d", i + 1);
- oh = omap_hwmod_lookup(oh_name);
- if (!oh)
- break;
-
- uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
- if (WARN_ON(!uart))
- return -ENODEV;
+ for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+ snprintf(omap_tty_name, MAX_UART_HWMOD_NAME_LEN,
+ "%s%d", OMAP_SERIAL_NAME, i);
+ if (cmdline_find_option(omap_tty_name)) {
+ omap_uart_con_id = i;
+ oh = omap_uart_hwmod_lookup(i);
+ oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+ return 0;
+ }
+ }
+ return 0;
+}
+core_initcall(omap_serial_early_init);
- uart->oh = oh;
- uart->num = i++;
- list_add_tail(&uart->node, &uart_list);
- num_uarts++;
+void __init omap_serial_init_port_pads(int id, struct omap_device_pad *pads,
+ int size, struct omap_uart_port_info *info)
+{
+ struct omap_board_data bdata;
- /*
- * NOTE: omap_hwmod_setup*() has not yet been called,
- * so no hwmod functions will work yet.
- */
+ bdata.id = id;
+ bdata.flags = 0;
+ bdata.pads = pads;
+ bdata.pads_cnt = size;
- /*
- * During UART early init, device need to be probed
- * to determine SoC specific init before omap_device
- * is ready. Therefore, don't allow idle here
- */
- uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
- } while (1);
+ if (!bdata.pads)
+ omap_serial_fill_default_pads(&bdata);
- return 0;
+ omap_serial_init_port(&bdata, info);
}
-core_initcall(omap_serial_early_init);
/**
* omap_serial_init_port() - initialize single serial port
* @bdata: port specific board data pointer
+ * @info: platform specific data pointer
*
* This function initialies serial driver for given port only.
* Platforms can call this function instead of omap_serial_init()
@@ -707,171 +387,114 @@ core_initcall(omap_serial_early_init);
* Don't mix calls to omap_serial_init_port() and omap_serial_init(),
* use only one of the two.
*/
-void __init omap_serial_init_port(struct omap_board_data *bdata)
+void __init omap_serial_init_port(struct omap_board_data *bdata,
+ struct omap_uart_port_info *info)
{
- struct omap_uart_state *uart;
struct omap_hwmod *oh;
struct omap_device *od;
- void *pdata = NULL;
- u32 pdata_size = 0;
- char *name;
-#ifndef CONFIG_SERIAL_OMAP
- struct plat_serial8250_port ports[2] = {
- {},
- {.flags = 0},
- };
- struct plat_serial8250_port *p = &ports[0];
-#else
- struct omap_uart_port_info omap_up;
-#endif
+ struct omap_uart_port_info *pdata;
+ char *name = DRIVER_NAME;
if (WARN_ON(!bdata))
return;
if (WARN_ON(bdata->id < 0))
return;
- if (WARN_ON(bdata->id >= num_uarts))
+ if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS))
return;
- list_for_each_entry(uart, &uart_list, node)
- if (bdata->id == uart->num)
- break;
-
- oh = uart->oh;
- uart->dma_enabled = 0;
-#ifndef CONFIG_SERIAL_OMAP
- name = "serial8250";
-
- /*
- * !! 8250 driver does not use standard IORESOURCE* It
- * has it's own custom pdata that can be taken from
- * the hwmod resource data. But, this needs to be
- * done after the build.
- *
- * ?? does it have to be done before the register ??
- * YES, because platform_device_data_add() copies
- * pdata, it does not use a pointer.
- */
- p->flags = UPF_BOOT_AUTOCONF;
- p->iotype = UPIO_MEM;
- p->regshift = 2;
- p->uartclk = OMAP24XX_BASE_BAUD * 16;
- p->irq = oh->mpu_irqs[0].irq;
- p->mapbase = oh->slaves[0]->addr->pa_start;
- p->membase = omap_hwmod_get_mpu_rt_va(oh);
- p->irqflags = IRQF_SHARED;
- p->private_data = uart;
-
- /*
- * omap44xx, ti816x: Never read empty UART fifo
- * omap3xxx: Never read empty UART fifo on UARTs
- * with IP rev >=0x52
- */
- uart->regshift = p->regshift;
- uart->membase = p->membase;
- if (cpu_is_omap44xx() || cpu_is_ti816x())
- uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
- else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
- >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
- uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-
- if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
- p->serial_in = serial_in_override;
- p->serial_out = serial_out_override;
- }
-
- pdata = &ports[0];
- pdata_size = 2 * sizeof(struct plat_serial8250_port);
-#else
+ oh = omap_uart_hwmod_lookup(bdata->id);
+ if (!oh)
+ return;
- name = DRIVER_NAME;
+ if (info == NULL)
+ info = omap_serial_default_info;
- omap_up.dma_enabled = uart->dma_enabled;
- omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
- omap_up.mapbase = oh->slaves[0]->addr->pa_start;
- omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
- omap_up.irqflags = IRQF_SHARED;
- omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("Memory allocation for UART pdata failed\n");
+ return;
+ }
- pdata = &omap_up;
- pdata_size = sizeof(struct omap_uart_port_info);
+ if (cpu_is_omap34xx() || cpu_is_omap44xx())
+ pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+
+ omap_uart_idle_init(pdata, bdata->id);
+
+ pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+ pdata->flags = UPF_BOOT_AUTOCONF;
+ pdata->enable_wakeup = omap_uart_wakeup_enable;
+ pdata->use_dma = info->use_dma;
+ pdata->chk_wakeup = omap_uart_chk_wakeup;
+ pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+ pdata->dma_rx_poll_rate = info->dma_rx_poll_rate;
+ pdata->dma_rx_timeout = info->dma_rx_timeout;
+ pdata->auto_sus_timeout = info->auto_sus_timeout;
+ pdata->wake_peer = info->wake_peer;
+ pdata->rts_mux_driver_control = info->rts_mux_driver_control;
+ if (bdata->id == omap_uart_con_id) {
+ pdata->console_uart = true;
+#ifdef CONFIG_DEBUG_LL
+ pdata->auto_sus_timeout = -1;
#endif
+ }
- if (WARN_ON(!oh))
- return;
+ if (pdata->use_dma &&
+ cpu_is_omap44xx() && omap_rev() > OMAP4430_REV_ES1_0)
+ pdata->errata |= OMAP4_UART_ERRATA_i659_TX_THR;
- od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
- omap_uart_latency,
- ARRAY_SIZE(omap_uart_latency), false);
+ od = omap_device_build(name, bdata->id, oh, pdata,
+ sizeof(*pdata), omap_uart_latency,
+ ARRAY_SIZE(omap_uart_latency), false);
WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
name, oh->name);
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
- uart->irq = oh->mpu_irqs[0].irq;
- uart->regshift = 2;
- uart->mapbase = oh->slaves[0]->addr->pa_start;
- uart->membase = omap_hwmod_get_mpu_rt_va(oh);
- uart->pdev = &od->pdev;
-
- oh->dev_attr = uart;
-
- console_lock(); /* in case the earlycon is on the UART */
-
- /*
- * Because of early UART probing, UART did not get idled
- * on init. Now that omap_device is ready, ensure full idle
- * before doing omap_device_enable().
- */
- omap_hwmod_idle(uart->oh);
-
- omap_device_enable(uart->pdev);
- omap_uart_idle_init(uart);
- omap_uart_reset(uart);
- omap_hwmod_enable_wakeup(uart->oh);
- omap_device_idle(uart->pdev);
-
- /*
- * Need to block sleep long enough for interrupt driven
- * driver to start. Console driver is in polling mode
- * so device needs to be kept enabled while polling driver
- * is in use.
- */
- if (uart->timeout)
- uart->timeout = (30 * HZ);
- omap_uart_block_sleep(uart);
- uart->timeout = DEFAULT_TIMEOUT;
-
- console_unlock();
-
- if ((cpu_is_omap34xx() && uart->padconf) ||
- (uart->wk_en && uart->wk_mask)) {
+ if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
+ (pdata->wk_en && pdata->wk_mask)) {
device_init_wakeup(&od->pdev.dev, true);
- DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
}
- /* Enable the MDR1 errata for OMAP3 */
- if (cpu_is_omap34xx() && !cpu_is_ti816x())
- uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+ kfree(pdata);
}
/**
- * omap_serial_init() - initialize all supported serial ports
+ * omap_serial_board_init() - initialize all supported serial ports
+ * @platform_data: platform specific data pointer
*
* Initializes all available UARTs as serial ports. Platforms
* can call this function when they want to have default behaviour
* for serial ports (e.g initialize them all as serial ports).
*/
-void __init omap_serial_init(void)
+void __init omap_serial_board_init(struct omap_uart_port_info *platform_data)
{
- struct omap_uart_state *uart;
struct omap_board_data bdata;
+ u8 i;
- list_for_each_entry(uart, &uart_list, node) {
- bdata.id = uart->num;
+ for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+ bdata.id = i;
bdata.flags = 0;
bdata.pads = NULL;
bdata.pads_cnt = 0;
- omap_serial_init_port(&bdata);
+ if (cpu_is_omap44xx() || cpu_is_omap34xx())
+ omap_serial_fill_default_pads(&bdata);
+
+ if (platform_data == NULL)
+ omap_serial_init_port(&bdata, NULL);
+ else
+ omap_serial_init_port(&bdata, &platform_data[i]);
}
}
+
+/**
+ * omap_serial_init() - initialize all supported serial ports
+ *
+ * Initializes all available UARTs.
+ * Platforms can call this function when they want to have default behaviour
+ * for serial ports (e.g initialize them all as serial ports).
+ */
+void __init omap_serial_init(void)
+{
+ omap_serial_board_init(NULL);
+}
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
new file mode 100644
index 0000000..b025e5f
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -0,0 +1,695 @@
+/*
+ * 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
+
+
+/*
+ * Macro to call PPA svc when MMU is OFF
+ * Caller must setup r0 and r3 before calling this macro
+ * @r0: PPA service ID
+ * @r3: Pointer to params
+*/
+.macro LM_CALL_PPA_SERVICE_PA
+ mov r1, #0x0 @ Process ID
+ mov r2, #0x4 @ Flag
+ mov r6, #0xff
+ mov r12, #0x00 @ Secure Service ID
+ dsb
+ smc #0
+.endm
+
+/*
+ * To load POR which was saved in SAR RAM
+ */
+POR_params:
+.word 1, 0
+
+
+ppa_zero_params:
+ .word 0x0
+
+/*
+ * =============================
+ * == 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
+ ands r5, r5, #0x0f
+ streq r6, [r8, #L2X0_SAVE_OFFSET0] @ Store save state
+ strne r6, [r8, #L2X0_SAVE_OFFSET1]
+ 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
+
+ bl omap4_get_sar_ram_base
+ ldr r9, [r0, #OMAP_TYPE_OFFSET]
+ cmp r9, #0x1 @ Check for HS device
+ bne skip_secure_l1_flush
+ mov r0, #SCU_PM_NORMAL
+ mov r1, #0xFF @ clean seucre L1
+ stmfd r13!, {r4-r12, r14}
+ ldr r12, =SCU_POWER_SECURE_INDEX
+ dsb
+ smc #0
+ dsb
+ ldmfd r13!, {r4-r12, r14}
+skip_secure_l1_flush:
+
+ /*
+ * 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]
+ ldrne r0, [r8, #SCU_OFFSET1]
+ mov r1, #0x00 @ Secure L1 is clean already
+ 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
+
+ mrc p15, 0, r0, c1, c1, 2 @Read NSACR data
+ tst r0, #(1 << 18)
+ mrcne p15, 0, r0, c1, c0, 1
+ bicne r0, r0, #(1 << 6)
+ mcrne p15, 0, r0, c1, c0, 1
+ isb
+
+
+#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
+ mrc p15, 0, r5, c0, c0, 5 @ Read MPIDR
+ ands r5, r5, #0x0f
+ ldreq r0, [r8, #L2X0_SAVE_OFFSET0]
+ ldrne r0, [r8, #L2X0_SAVE_OFFSET1]
+ 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
+ ldr r0, =0xffff
+ str r0, [r2, #L2X0_CLEAN_INV_WAY]
+wait:
+ ldr r0, [r2, #L2X0_CLEAN_INV_WAY]
+ ands r0, r0, #0xff
+ bne wait
+#ifdef CONFIG_PL310_ERRATA_727915
+ mov r0, #0x00
+ mov r12, #0x100
+ dsb
+ smc #0
+ dsb
+#endif
+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
+
+do_WFI:
+ bl omap_do_wfi
+
+ /*
+ * 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
+
+ /* Enable SMP bit if it's being disabled */
+ mrc p15, 0, r0, c1, c0, 1
+ tst r0, #(1 << 6) @ Check SMP bit enabled?
+ orreq r0, r0, #(1 << 6)
+ mcreq p15, 0, r0, c1, c0, 1
+ 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)
+ /*
+ * CPU1 must check if CPU0 is alive/awaken.
+ * if PL310 is OFF, MPUSS was OFF and CPU0 is still off,
+ * CPU1 must go to sleep and wait for CPU0.
+ * CPU0 is needed for any PPA API to work.
+ */
+ mrc p15, 0, r0, c0, c0, 5 @ Get cpuID
+ ands r0, r0, #0x0f @ Continue boot if CPU0
+ beq continue_boot
+ ldr r8, =OMAP44XX_SAR_RAM_BASE
+ ldr r9, [r8, #OMAP_TYPE_OFFSET]
+ cmp r9, #0x1 @ Check for HS device
+ bne continue_boot @ Continue on GP devcies
+ ldr r2, =OMAP44XX_L2CACHE_BASE
+ ldr r0, [r2, #L2X0_CTRL]
+ and r0, #0x0f
+ cmp r0, #1 @ is CPU0 already UP?
+ beq ppa_cp15_cpu1_configure @ CPU1 HS go to next stage
+ /*
+ * When CPU1 is released to control of HLOS in the case of OSWR
+ * and OFF mode, PPA below v1.7.3[1] is not performing all
+ * Memory coherency and TLB operations required.
+ *
+ * A WA to recover cleanly from this scenario is to switch CPU1 back to
+ * previous OFF state. This forces a reset of CPU1, which in turn
+ * forces CPU1 not to override MMU descriptors already in place in
+ * internal RAM setup by CPU0. CPU1 will also sync to the in-place
+ * descriptors on the next wakeup. CPU1 wakeup is done by
+ * later kernel subsystems depending on suspend or cpuidle path
+ * being exercised.
+ * NOTE - for OSWR, state provided is 2, and for OFF, state is 3,
+ * Since the bug impacts OFF and OSWR, we need to force a 0x3 to
+ * shut off CPU1
+ *
+ * Since many distributions may not be able to update PPA OR would like
+ * to support platforms with older PPA, we provide a config option.
+ * This is simpler and makes the current code remain cleaner in
+ * comparison to a flag based handling in CPU1 recovery for
+ * board + PPA revision combinations.
+ *
+ * Having this config option enabled even on platforms with fixed PPA
+ * should not impact stability, however, ability to make CPU1 available
+ * for operations a little earlier is curtailed.
+ *
+ * Foot note [1]:
+ * v1.7.3 is the official TI PPA version. Custom PPA could have
+ * the relevant changes ported over to it.
+ */
+#ifdef CONFIG_OMAP4_PPA_CPU1_ONLINE_BUG
+ mov r0, #0x03 @ target CPU1 to OFF(mpusspd=OSWR/OFF)
+ mov r1, #0x00 @ Secure L1 is already clean
+ ldr r12, =SCU_POWER_SECURE_INDEX
+ dsb
+ smc #0
+
+ isb @ Necessary barriers before wfi
+ dsb
+ dmb
+ wfi @ wait for interrupt
+ nop
+ nop
+
+ /*
+ * IF we came out of WFI immediately, something unknown happend.
+ * Fall through AND loop back to the checks. Failing which retry WFI.
+ */
+#endif
+ /*
+ * CPU0 and CPU1 are release together from OFF mode, however,
+ * CPU0 can be busy doing restore operations while waking
+ * from OFF mode, However, for many PPA services we need
+ * CPU0, so, we ask CPU1 to loop back to stagger CPU1 behind CPU0
+ */
+ b omap4_cpu_resume
+
+ppa_cp15_cpu1_configure:
+ /*
+ * Configure CP15 for CPU1 on HS devices:
+ * In HS devices CPU0's CP15 is configured at wakeup by PPA, CPU1 must
+ * call PPA to configure it.
+ * In 4430 devices CPU1 this call also enables the access to SMP bit,
+ * on 4460 devices, CPU1 will have SMP bit access by default.
+ */
+ mov r0, #PPA_SERVICE_DEFAULT_POR_NS_SMP
+ adr r3, ppa_zero_params @ Pointer to parameters
+ LM_CALL_PPA_SERVICE_PA
+ isb
+ dsb
+ cmp r0, #0x0 @ API returns 0 on success.
+ bne ppa_cp15_cpu1_configure @ retry if we did succeed
+
+ /* Fall through to continue with boot */
+
+continue_boot:
+
+#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
+
+check_por:
+ ldr r0, =OMAP44XX_SAR_RAM_BASE @ Check DEVICE type
+ ldr r1, [r0, #OMAP_TYPE_OFFSET]
+ cmp r1, #0x1 @ Check for HS device
+ bne skip_por
+ ldr r0, =PPA_SERVICE_PL310_POR @ Setup PPA HAL call
+ ldr r1, =OMAP44XX_SAR_RAM_BASE
+ ldr r4, [r1, #L2X0_PREFETCHCTRL_OFFSET]
+ adr r3, POR_params
+ str r4, [r3, #0x04]
+ LM_CALL_PPA_SERVICE_PA
+skip_por:
+ ldr r3, =OMAP44XX_SAR_RAM_BASE
+ ldr r0, [r3, #L2X0_AUXCTRL_OFFSET]
+ ldr r12, =0x109 @ Setup L2 AUXCTRL value
+ dsb
+ smc #0
+
+ ldr r2, =OMAP44XX_L2CACHE_BASE
+ ldr r4, =OMAP44XX_SAR_RAM_BASE
+ ldr r9, [r4, #L2X0_LOCKDOWN_OFFSET0]
+ str r9, [r2, #L2X0_LOCKDOWN_WAY_D0]
+ str r9, [r2, #L2X0_LOCKDOWN_WAY_D1]
+ str r9, [r2, #L2X0_LOCKDOWN_WAY_I0]
+ str r9, [r2, #L2X0_LOCKDOWN_WAY_I1]
+
+ dsb
+ mov r0, #0x1
+ ldr r12, =0x102 @ Enable L2 Cache controller
+ dsb
+ smc #0
+ dsb
+skip_l2en:
+#endif
+
+ /* Check if we have Public access to SMP bit */
+ mrc p15, 0, r0, c1, c1, 2 @ Read NSACR data
+ tst r0, #(1 << 18)
+ beq skip_ns_smp_enable @ Skip if still no access
+
+ /* Set the SMP bit if it is not already set */
+ mrc p15, 0, r0, c1, c0, 1
+ tst r0, #(1 << 6) @ Check SMP bit enabled?
+ orreq r0, r0, #(1 << 6)
+ mcreq p15, 0, r0, c1, c0, 1
+ isb
+skip_ns_smp_enable:
+
+ /*
+ * 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)
+
+ENTRY(omap_bus_sync)
+ stmfd sp!, {r9, lr}
+ /* SO write to drain of MPU-2-DDR T2ASYNC FIFO */
+ bl omap_get_dram_barrier_base
+ ldr r2, [r0]
+ str r2, [r0]
+ /* SO write to drain MPU-2-L3 T2ASYNC FIFO */
+ bl omap_get_sram_barrier_base
+ ldr r2, [r0]
+ str r2, [r0]
+ isb
+ ldmfd sp!, {r9, pc}
+ENDPROC(omap_bus_sync)
+
+ENTRY(omap_do_wfi)
+ stmfd sp!, {lr}
+ /* Drain interconnect write buffers. */
+ bl omap_bus_sync
+
+ /*
+ * 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
+
+ ldmfd sp!, {pc}
+ENDPROC(omap_do_wfi)
+
+#endif
diff --git a/arch/arm/mach-omap2/smartreflex-class1p5.c b/arch/arm/mach-omap2/smartreflex-class1p5.c
new file mode 100644
index 0000000..2090884
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex-class1p5.c
@@ -0,0 +1,678 @@
+/*
+ * Smart reflex Class 1.5 specific implementations
+ *
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ * Nishanth Menon <nm@ti.com>
+ *
+ * Smart reflex class 1.5 is also called periodic SW Calibration
+ * Some of the highlights are as follows:
+ * – Host CPU triggers OPP calibration when transitioning to non calibrated
+ * OPP
+ * – SR-AVS + VP modules are used to perform calibration
+ * – Once completed, the SmartReflex-AVS module can be disabled
+ * – Enables savings based on process, supply DC accuracy and aging
+ *
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/kobject.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/opp.h>
+
+#include "smartreflex.h"
+#include "voltage.h"
+#include "dvfs.h"
+
+#define MAX_VDDS 3
+#define SR1P5_SAMPLING_DELAY_MS 1
+#define SR1P5_STABLE_SAMPLES 10
+#define SR1P5_MAX_TRIGGERS 5
+
+/*
+ * We expect events in 10uS, if we don't receive it in twice as long,
+ * we stop waiting for the event and use the current value
+ */
+#define MAX_CHECK_VPTRANS_US 20
+
+/**
+ * struct sr_class1p5_work_data - data meant to be used by calibration work
+ * @work: calibration work
+ * @voltdm: voltage domain for which we are triggering
+ * @vdata: voltage data we are calibrating
+ * @num_calib_triggers: number of triggers from calibration loop
+ * @num_osc_samples: number of samples collected by isr
+ * @u_volt_samples: private data for collecting voltage samples in
+ * case oscillations. filled by the notifier and
+ * consumed by the work item.
+ * @work_active: have we scheduled a work item?
+ */
+struct sr_class1p5_work_data {
+ struct delayed_work work;
+ struct voltagedomain *voltdm;
+ struct omap_volt_data *vdata;
+ u8 num_calib_triggers;
+ u8 num_osc_samples;
+ unsigned long u_volt_samples[SR1P5_STABLE_SAMPLES];
+ bool work_active;
+};
+
+#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY
+/* recal_work: recalibration calibration work */
+static struct delayed_work recal_work;
+#endif
+
+/**
+ * sr_class1p5_notify() - isr notifier for status events
+ * @voltdm: voltage domain for which we were triggered
+ * @voltdm_cdata: voltage domain specific private class data
+ * @status: notifier event to use
+ *
+ * This basically collects data for the work to use.
+ */
+static int sr_class1p5_notify(struct voltagedomain *voltdm,
+ void *voltdm_cdata,
+ u32 status)
+{
+ struct sr_class1p5_work_data *work_data;
+ int idx = 0;
+
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_err("%s: bad parameters!\n", __func__);
+ return -EINVAL;
+ }
+
+ work_data = (struct sr_class1p5_work_data *)voltdm_cdata;
+ if (IS_ERR_OR_NULL(work_data)) {
+ pr_err("%s:%s no work data!!\n", __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ /* Wait for transdone so that we know the voltage to read */
+ do {
+ if (omap_vp_is_transdone(voltdm))
+ break;
+ idx++;
+ /* get some constant delay */
+ udelay(1);
+ } while (idx < MAX_CHECK_VPTRANS_US);
+
+ /*
+ * NOTE:
+ * If we timeout, we still read the data,
+ * if we are oscillating+irq latencies are too high, we could
+ * have scenarios where we miss transdone event. since
+ * we waited long enough, it is still safe to read the voltage
+ * as we would have waited long enough - Dont warn for this.
+ */
+ idx = (work_data->num_osc_samples) % SR1P5_STABLE_SAMPLES;
+ work_data->u_volt_samples[idx] = omap_vp_get_curr_volt(voltdm);
+ work_data->num_osc_samples++;
+
+ omap_vp_clear_transdone(voltdm);
+
+
+ return 0;
+}
+
+/**
+ * sr_class1p5_calib_work() - work which actually does the calibration
+ * @work: pointer to the work
+ *
+ * calibration routine uses the following logic:
+ * on the first trigger, we start the isr to collect sr voltages
+ * wait for stabilization delay (reschdule self instead of sleeping)
+ * after the delay, see if we collected any isr events
+ * if none, we have calibrated voltage.
+ * if there are any, we retry untill we giveup.
+ * on retry timeout, select a voltage to use as safe voltage.
+ */
+static void sr_class1p5_calib_work(struct work_struct *work)
+{
+ struct sr_class1p5_work_data *work_data =
+ container_of(work, struct sr_class1p5_work_data, work.work);
+ unsigned long u_volt_safe = 0, u_volt_current = 0, u_volt_margin = 0;
+ struct omap_volt_data *volt_data;
+ struct voltagedomain *voltdm;
+ int idx = 0;
+
+ if (!work) {
+ pr_err("%s: ooops.. null work_data?\n", __func__);
+ return;
+ }
+
+ /*
+ * Handle the case where we might have just been scheduled AND
+ * 1.5 disable was called.
+ */
+ if (!mutex_trylock(&omap_dvfs_lock)) {
+ schedule_delayed_work(&work_data->work,
+ msecs_to_jiffies(SR1P5_SAMPLING_DELAY_MS *
+ SR1P5_STABLE_SAMPLES));
+ return;
+ }
+
+ voltdm = work_data->voltdm;
+ /*
+ * In the unlikely case that we did get through when unplanned,
+ * flag and return.
+ */
+ if (unlikely(!work_data->work_active)) {
+ pr_err("%s:%s unplanned work invocation!\n", __func__,
+ voltdm->name);
+ mutex_unlock(&omap_dvfs_lock);
+ return;
+ }
+
+ volt_data = work_data->vdata;
+
+ work_data->num_calib_triggers++;
+ /* if we are triggered first time, we need to start isr to sample */
+ if (work_data->num_calib_triggers == 1) {
+ /* We could be interrupted many times, so, only for debug */
+ pr_debug("%s: %s: Calibration start: Voltage Nominal=%d\n",
+ __func__, voltdm->name, volt_data->volt_nominal);
+ goto start_sampling;
+ }
+
+ /* Stop isr from interrupting our measurements :) */
+ sr_notifier_control(voltdm, false);
+
+ /*
+ * Quit sampling
+ * a) if we have oscillations
+ * b) if we have nominal voltage as the voltage
+ */
+ if (work_data->num_calib_triggers == SR1P5_MAX_TRIGGERS)
+ goto stop_sampling;
+
+ /* if there are no samples captured.. SR is silent, aka stability! */
+ if (!work_data->num_osc_samples) {
+ /* Did we interrupt too early? */
+ u_volt_current = omap_vp_get_curr_volt(voltdm);
+ if (u_volt_current >= volt_data->volt_nominal)
+ goto start_sampling;
+ u_volt_safe = u_volt_current;
+ goto done_calib;
+ }
+
+ /* we have potential oscillations/first sample */
+start_sampling:
+ work_data->num_osc_samples = 0;
+
+ /* Clear transdone events so that we can go on. */
+ do {
+ if (!omap_vp_is_transdone(voltdm))
+ break;
+ idx++;
+ /* get some constant delay */
+ udelay(1);
+ omap_vp_clear_transdone(voltdm);
+ } while (idx < MAX_CHECK_VPTRANS_US);
+ if (idx >= MAX_CHECK_VPTRANS_US)
+ pr_warning("%s: timed out waiting for transdone clear!!\n",
+ __func__);
+
+ /* Clear pending events */
+ sr_notifier_control(voltdm, false);
+ /* trigger sampling */
+ sr_notifier_control(voltdm, true);
+ schedule_delayed_work(&work_data->work,
+ msecs_to_jiffies(SR1P5_SAMPLING_DELAY_MS *
+ SR1P5_STABLE_SAMPLES));
+ mutex_unlock(&omap_dvfs_lock);
+ return;
+
+stop_sampling:
+ /*
+ * We are here for Oscillations due to two scenarios:
+ * a) SR is attempting to adjust voltage lower than VLIMITO
+ * which VP will ignore, but SR will re-attempt
+ * b) actual oscillations
+ * NOTE: For debugging, enable debug to see the samples.
+ */
+ pr_warning("%s: %s Stop sampling: Voltage Nominal=%d samples=%d\n",
+ __func__, work_data->voltdm->name,
+ volt_data->volt_nominal, work_data->num_osc_samples);
+
+ /* pick up current voltage */
+ u_volt_current = omap_vp_get_curr_volt(voltdm);
+
+ /* Just in case we got more interrupts than our tiny buffer */
+ if (work_data->num_osc_samples > SR1P5_STABLE_SAMPLES)
+ idx = SR1P5_STABLE_SAMPLES;
+ else
+ idx = work_data->num_osc_samples;
+ /* Index at 0 */
+ idx -= 1;
+ u_volt_safe = u_volt_current;
+ /* Grab the max of the samples as the stable voltage */
+ for (; idx >= 0; idx--) {
+ pr_debug("%s: osc_v[%d]=%ld, safe_v=%ld\n", __func__, idx,
+ work_data->u_volt_samples[idx], u_volt_safe);
+ if (work_data->u_volt_samples[idx] > u_volt_safe)
+ u_volt_safe = work_data->u_volt_samples[idx];
+ }
+
+ /* Fall through to close up common stuff */
+done_calib:
+ sr_disable_errgen(voltdm);
+ omap_vp_disable(voltdm);
+ sr_disable(voltdm);
+
+ /* Add margin if needed */
+ if (volt_data->volt_margin) {
+ struct omap_voltdm_pmic *pmic = voltdm->pmic;
+ /* Convert to rounded to PMIC step level if available */
+ if (pmic && pmic->vsel_to_uv && pmic->uv_to_vsel) {
+ /*
+ * To ensure conversion works:
+ * use a proper base voltage - we use the current volt
+ * then convert it with pmic routine to vsel and back
+ * to voltage, and finally remove the base voltage
+ */
+ u_volt_margin = u_volt_current + volt_data->volt_margin;
+ u_volt_margin = pmic->uv_to_vsel(u_volt_margin);
+ u_volt_margin = pmic->vsel_to_uv(u_volt_margin);
+ u_volt_margin -= u_volt_current;
+ } else {
+ u_volt_margin = volt_data->volt_margin;
+ }
+
+ u_volt_safe += u_volt_margin;
+ }
+
+ if (u_volt_safe > volt_data->volt_nominal) {
+ pr_warning("%s: %s Vsafe %ld > Vnom %d. %ld[%d] margin on"
+ "vnom %d curr_v=%ld\n", __func__, voltdm->name,
+ u_volt_safe, volt_data->volt_nominal, u_volt_margin,
+ volt_data->volt_margin, volt_data->volt_nominal,
+ u_volt_current);
+ }
+
+ volt_data->volt_calibrated = u_volt_safe;
+ /* Setup my dynamic voltage for the next calibration for this opp */
+ volt_data->volt_dynamic_nominal = omap_get_dyn_nominal(volt_data);
+
+ /*
+ * if the voltage we decided as safe is not the current voltage,
+ * switch
+ */
+ if (volt_data->volt_calibrated != u_volt_current) {
+ pr_debug("%s: %s reconfiguring to voltage %d\n",
+ __func__, voltdm->name, volt_data->volt_calibrated);
+ voltdm_scale(voltdm, volt_data);
+ }
+
+ pr_info("%s: %s: Calibration complete: Voltage:Nominal=%d,"
+ "Calib=%d,margin=%d\n",
+ __func__, voltdm->name, volt_data->volt_nominal,
+ volt_data->volt_calibrated, volt_data->volt_margin);
+ /*
+ * TODO: Setup my wakeup voltage to allow immediate going to OFF and
+ * on - Pending twl and voltage layer cleanups.
+ * This is necessary, as this is not done as part of regular
+ * Dvfs flow.
+ * vc_setup_on_voltage(voltdm, volt_data->volt_calibrated);
+ */
+ work_data->work_active = false;
+ mutex_unlock(&omap_dvfs_lock);
+}
+
+#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY
+
+/**
+ * sr_class1p5_voltdm_recal() - Helper routine to reset calibration.
+ * @voltdm: Voltage domain to reset calibration for
+ * @user: unused
+ *
+ * NOTE: Appropriate locks must be held by calling path to ensure mutual
+ * exclusivity
+ */
+static int sr_class1p5_voltdm_recal(struct voltagedomain *voltdm,
+ void *user)
+{
+ struct omap_volt_data *vdata;
+
+ /*
+ * we need to go no further if sr is not enabled for this domain or
+ * voltage processor is not present for this voltage domain
+ * (example vdd_wakeup). Class 1.5 requires Voltage processor
+ * to function.
+ */
+ if (!voltdm->vp || !is_sr_enabled(voltdm))
+ return 0;
+
+ vdata = omap_voltage_get_curr_vdata(voltdm);
+ if (!vdata) {
+ pr_err("%s: unable to find current voltage for vdd_%s\n",
+ __func__, voltdm->name);
+ return -ENXIO;
+ }
+
+ omap_sr_disable(voltdm);
+ omap_voltage_calib_reset(voltdm);
+ voltdm_reset(voltdm);
+ omap_sr_enable(voltdm, vdata);
+ pr_info("%s: %s: calibration reset\n", __func__, voltdm->name);
+
+ return 0;
+}
+
+/**
+ * sr_class1p5_recal_work() - work which actually does the calibration
+ * @work: pointer to the work
+ *
+ * on a periodic basis, we come and reset our calibration setup
+ * so that a recalibration of the OPPs take place. This takes
+ * care of aging factor in the system.
+ */
+static void sr_class1p5_recal_work(struct work_struct *work)
+{
+ mutex_lock(&omap_dvfs_lock);
+ if (voltdm_for_each(sr_class1p5_voltdm_recal, NULL))
+ pr_err("%s: Recalibration failed\n", __func__);
+ mutex_unlock(&omap_dvfs_lock);
+ /* We come back again after time the usual delay */
+ schedule_delayed_work(&recal_work,
+ msecs_to_jiffies
+ (CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY));
+}
+#endif /* CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY */
+
+/**
+ * sr_class1p5_enable() - class 1.5 mode of enable for a voltage domain
+ * @voltdm: voltage domain to enable SR for
+ * @voltdm_cdata: voltage domain specific private class data
+ * @volt_data: voltdata for the current OPP being transitioned to
+ *
+ * when this gets called, we use the h/w loop to setup our voltages
+ * to an calibrated voltage, detect any oscillations, recover from the same
+ * and finally store the optimized voltage as the calibrated voltage in the
+ * system.
+ *
+ * NOTE: Appropriate locks must be held by calling path to ensure mutual
+ * exclusivity
+ */
+static int sr_class1p5_enable(struct voltagedomain *voltdm,
+ void *voltdm_cdata,
+ struct omap_volt_data *volt_data)
+{
+ int r;
+ struct sr_class1p5_work_data *work_data;
+
+ if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(volt_data)) {
+ pr_err("%s: bad parameters!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* If already calibrated, nothing to do here.. */
+ if (volt_data->volt_calibrated)
+ return 0;
+
+ work_data = (struct sr_class1p5_work_data *)voltdm_cdata;
+ if (IS_ERR_OR_NULL(work_data)) {
+ pr_err("%s: bad work data??\n", __func__);
+ return -EINVAL;
+ }
+
+ if (work_data->work_active)
+ return 0;
+
+ omap_vp_enable(voltdm);
+ r = sr_enable(voltdm, volt_data);
+ if (r) {
+ pr_err("%s: sr[%s] failed\n", __func__, voltdm->name);
+ sr_disable_errgen(voltdm);
+ omap_vp_disable(voltdm);
+ return r;
+ }
+ work_data->vdata = volt_data;
+ work_data->work_active = true;
+ work_data->num_calib_triggers = 0;
+ /* program the workqueue and leave it to calibrate offline.. */
+ schedule_delayed_work(&work_data->work,
+ msecs_to_jiffies(SR1P5_SAMPLING_DELAY_MS *
+ SR1P5_STABLE_SAMPLES));
+
+ return 0;
+}
+
+/**
+ * sr_class1p5_disable() - disable 1.5 mode for a voltage domain
+ * @voltdm: voltage domain for the sr which needs disabling
+ * @volt_data: voltage data for current OPP to disable
+ * @voltdm_cdata: voltage domain specific private class data
+ * @is_volt_reset: reset the voltage?
+ *
+ * This function has the necessity to either disable SR alone OR disable SR
+ * and reset voltage to appropriate level depending on is_volt_reset parameter.
+ *
+ * Disabling SR H/w loop:
+ * If calibration is complete or not yet triggered, we have no need to disable
+ * SR h/w loop.
+ * If calibration is complete, we would have already disabled SR AVS at the end
+ * of calibration and h/w loop is inactive when this is called.
+ * If it was never calibrated before, H/w loop was never enabled in the first
+ * place to disable.
+ * If calibration is underway, we cancel the work queue and disable SR. This is
+ * to provide priority to DVFS transition as such transitions cannot wait
+ * without impacting user experience.
+ *
+ * Resetting voltage:
+ * If we have already completed calibration, then resetting to nominal voltage
+ * is not required as we are functioning at safe voltage levels.
+ * If we have not started calibration, we would like to reset to nominal voltage
+ * If calibration is underway and we are attempting to reset voltage as
+ * well, it implies we are in idle/suspend paths where we give priority
+ * to calibration activity and a retry will be attempted.
+ *
+ * NOTE: Appropriate locks must be held by calling path to ensure mutual
+ * exclusivity
+ */
+static int sr_class1p5_disable(struct voltagedomain *voltdm,
+ void *voltdm_cdata,
+ struct omap_volt_data *volt_data,
+ int is_volt_reset)
+{
+ struct sr_class1p5_work_data *work_data;
+
+ if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(volt_data)) {
+ pr_err("%s: bad parameters!\n", __func__);
+ return -EINVAL;
+ }
+
+ work_data = (struct sr_class1p5_work_data *)voltdm_cdata;
+ if (IS_ERR_OR_NULL(work_data)) {
+ pr_err("%s: bad work data??\n", __func__);
+ return -EINVAL;
+ }
+ if (work_data->work_active) {
+ /* if volt reset and work is active, we dont allow this */
+ if (is_volt_reset)
+ return -EBUSY;
+ /* flag work is dead and remove the old work */
+ work_data->work_active = false;
+ cancel_delayed_work_sync(&work_data->work);
+ sr_notifier_control(voltdm, false);
+ sr_disable_errgen(voltdm);
+ omap_vp_disable(voltdm);
+ sr_disable(voltdm);
+ }
+
+ /* If already calibrated, don't need to reset voltage */
+ if (volt_data->volt_calibrated)
+ return 0;
+
+ if (is_volt_reset)
+ voltdm_reset(voltdm);
+ return 0;
+}
+
+/**
+ * sr_class1p5_configure() - configuration function
+ * @voltdm: configure for which voltage domain
+ * @voltdm_cdata: voltage domain specific private class data
+ *
+ * we dont do much here other than setup some registers for
+ * the sr module involved.
+ */
+static int sr_class1p5_configure(struct voltagedomain *voltdm,
+ void *voltdm_cdata)
+{
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_err("%s: bad parameters!\n", __func__);
+ return -EINVAL;
+ }
+
+ return sr_configure_errgen(voltdm);
+}
+
+/**
+ * sr_class1p5_init() - class 1p5 init
+ * @voltdm: sr voltage domain
+ * @voltdm_cdata: voltage domain specific private class data
+ * allocated by class init with work item data
+ * freed by deinit.
+ * @class_priv_data: private data for the class (unused)
+ *
+ * we do class specific initialization like creating sysfs/debugfs entries
+ * needed, spawning of a kthread if needed etc.
+ */
+static int sr_class1p5_init(struct voltagedomain *voltdm,
+ void **voltdm_cdata, void *class_priv_data)
+{
+ struct sr_class1p5_work_data *work_data;
+
+ if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(voltdm_cdata)) {
+ pr_err("%s: bad parameters!\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!IS_ERR_OR_NULL(*voltdm_cdata)) {
+ pr_err("%s: ooopps.. class already initialized for %s! bug??\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+ /* setup our work params */
+ work_data = kzalloc(sizeof(struct sr_class1p5_work_data), GFP_KERNEL);
+ if (!work_data) {
+ pr_err("%s: no memory to allocate work data on domain %s\n",
+ __func__, voltdm->name);
+ return -ENOMEM;
+ }
+
+ work_data->voltdm = voltdm;
+ INIT_DELAYED_WORK_DEFERRABLE(&work_data->work, sr_class1p5_calib_work);
+ *voltdm_cdata = (void *)work_data;
+
+ return 0;
+}
+
+/**
+ * sr_class1p5_deinit() - class 1p5 deinitialization
+ * @voltdm: voltage domain for which to do this.
+ * @voltdm_cdata: voltage domain specific private class data
+ * allocated by class init with work item data
+ * freed by deinit.
+ * @class_priv_data: class private data for deinitialiation (unused)
+ *
+ * currently only resets the calibrated voltage forcing DVFS voltages
+ * to be used in the system
+ *
+ * NOTE: Appropriate locks must be held by calling path to ensure mutual
+ * exclusivity
+ */
+static int sr_class1p5_deinit(struct voltagedomain *voltdm,
+ void **voltdm_cdata, void *class_priv_data)
+{
+ struct sr_class1p5_work_data *work_data;
+
+ if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(voltdm_cdata)) {
+ pr_err("%s: bad parameters!\n", __func__);
+ return -EINVAL;
+ }
+
+ if (IS_ERR_OR_NULL(*voltdm_cdata)) {
+ pr_err("%s: ooopps.. class not initialized for %s! bug??\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ work_data = (struct sr_class1p5_work_data *) *voltdm_cdata;
+
+ /*
+ * we dont have SR periodic calib anymore.. so reset calibs
+ * we are already protected by appropriate locks, so no lock needed
+ * here.
+ */
+ if (work_data->work_active)
+ sr_class1p5_disable(voltdm, work_data, work_data->vdata, 0);
+
+ /* Ensure worker canceled. */
+ cancel_delayed_work_sync(&work_data->work);
+ omap_voltage_calib_reset(voltdm);
+ voltdm_reset(voltdm);
+
+ *voltdm_cdata = NULL;
+ kfree(work_data);
+
+ return 0;
+}
+
+/* SR class1p5 structure */
+static struct omap_sr_class_data class1p5_data = {
+ .enable = sr_class1p5_enable,
+ .disable = sr_class1p5_disable,
+ .configure = sr_class1p5_configure,
+ .class_type = SR_CLASS1P5,
+ .init = sr_class1p5_init,
+ .deinit = sr_class1p5_deinit,
+ .notify = sr_class1p5_notify,
+ /*
+ * trigger for bound - this tells VP that SR has a voltage
+ * change. we should try and ensure transdone is set before reading
+ * vp voltage.
+ */
+ .notify_flags = SR_NOTIFY_MCUBOUND,
+};
+
+/**
+ * sr_class1p5_driver_init() - register class 1p5 as default
+ *
+ * board files call this function to use class 1p5, we register with the
+ * smartreflex subsystem
+ */
+static int __init sr_class1p5_driver_init(void)
+{
+ int r;
+
+ /* Enable this class only for OMAP3630 and OMAP4 */
+ if (!(cpu_is_omap3630() || cpu_is_omap44xx()))
+ return -EINVAL;
+
+ r = sr_register_class(&class1p5_data);
+ if (r) {
+ pr_err("SmartReflex class 1.5 driver: "
+ "failed to register with %d\n", r);
+ } else {
+#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY
+ INIT_DELAYED_WORK_DEFERRABLE(&recal_work,
+ sr_class1p5_recal_work);
+ schedule_delayed_work(&recal_work,
+ msecs_to_jiffies
+ (CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY));
+#endif
+ pr_info("SmartReflex class 1.5 driver: initialized (%dms)\n",
+ CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY);
+ }
+ return r;
+}
+late_initcall(sr_class1p5_driver_init);
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index f438cf4..9ac1c99 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -11,33 +11,33 @@
* published by the Free Software Foundation.
*/
+#include <plat/cpu.h>
#include "smartreflex.h"
-static int sr_class3_enable(struct voltagedomain *voltdm)
+static int sr_class3_enable(struct voltagedomain *voltdm,
+ void *voltdm_cdata,
+ struct omap_volt_data *volt_data)
{
- unsigned long volt = omap_voltage_get_nom_volt(voltdm);
-
- if (!volt) {
- pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
- __func__, voltdm->name);
- return -ENODATA;
- }
-
omap_vp_enable(voltdm);
- return sr_enable(voltdm, volt);
+ return sr_enable(voltdm, volt_data);
}
-static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
+static int sr_class3_disable(struct voltagedomain *voltdm,
+ void *voltdm_cdata,
+ struct omap_volt_data *vdata,
+ int is_volt_reset)
{
+ sr_disable_errgen(voltdm);
omap_vp_disable(voltdm);
sr_disable(voltdm);
if (is_volt_reset)
- omap_voltage_reset(voltdm);
+ voltdm_reset(voltdm);
return 0;
}
-static int sr_class3_configure(struct voltagedomain *voltdm)
+static int sr_class3_configure(struct voltagedomain *voltdm,
+ void *voltdm_cdata)
{
return sr_configure_errgen(voltdm);
}
@@ -53,6 +53,10 @@ static struct omap_sr_class_data class3_data = {
/* Smartreflex Class3 init API to be called from board file */
static int __init sr_class3_init(void)
{
+ /* Enable this class only for OMAP343x */
+ if (!cpu_is_omap343x())
+ return -EINVAL;
+
pr_info("SmartReflex Class3 initialized\n");
return sr_register_class(&class3_data);
}
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index f5a6bc1..c2d85c1 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -28,6 +28,7 @@
#include <plat/common.h>
#include "pm.h"
+#include "dvfs.h"
#include "smartreflex.h"
#define SMARTREFLEX_NAME_LEN 16
@@ -49,11 +50,14 @@ struct omap_sr {
u32 senp_mod;
u32 senn_mod;
unsigned int irq;
+ bool irq_enabled;
void __iomem *base;
struct platform_device *pdev;
struct list_head node;
struct omap_sr_nvalue_table *nvalue_table;
struct voltagedomain *voltdm;
+ /* Managed by class driver as needed */
+ void *voltdm_cdata;
struct dentry *dbg_dir;
};
@@ -62,6 +66,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)
{
@@ -72,10 +77,6 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
u32 value)
{
u32 reg_val;
- u32 errconfig_offs = 0, errconfig_mask = 0;
-
- reg_val = __raw_readl(sr->base + offset);
- reg_val &= ~mask;
/*
* Smartreflex error config register is special as it contains
@@ -86,16 +87,15 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
* if they are currently set, but does allow the caller to write
* those bits.
*/
- if (sr->ip_type == SR_TYPE_V1) {
- errconfig_offs = ERRCONFIG_V1;
- errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
- } else if (sr->ip_type == SR_TYPE_V2) {
- errconfig_offs = ERRCONFIG_V2;
- errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
- }
+ if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1)
+ mask |= ERRCONFIG_STATUS_V1_MASK;
+ else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2)
+ mask |= ERRCONFIG_VPBOUNDINTST_V2;
+
+ reg_val = __raw_readl(sr->base + offset);
+ reg_val &= ~mask;
- if (offset == errconfig_offs)
- reg_val &= ~errconfig_mask;
+ value &= mask;
reg_val |= value;
@@ -124,27 +124,119 @@ static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
return ERR_PTR(-ENODATA);
}
+static inline u32 notifier_to_irqen_v1(u8 notify_flags)
+{
+ u32 val;
+
+ val = (notify_flags & SR_NOTIFY_MCUACCUM) ?
+ ERRCONFIG_MCUACCUMINTEN : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUVALID) ?
+ ERRCONFIG_MCUVALIDINTEN : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUBOUND) ?
+ ERRCONFIG_MCUBOUNDINTEN : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUDISACK) ?
+ ERRCONFIG_MCUDISACKINTEN : 0;
+
+ return val;
+}
+
+static inline u32 notifier_to_irqen_v2(u8 notify_flags)
+{
+ u32 val;
+
+ val = (notify_flags & SR_NOTIFY_MCUACCUM) ?
+ IRQENABLE_MCUACCUMINT : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUVALID) ?
+ IRQENABLE_MCUVALIDINT : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUBOUND) ?
+ IRQENABLE_MCUBOUNDSINT : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUDISACK) ?
+ IRQENABLE_MCUDISABLEACKINT : 0;
+
+ return val;
+}
+
+static inline u8 irqstat_to_notifier_v1(u32 status)
+{
+ u8 val;
+
+ val = (status & ERRCONFIG_MCUACCUMINTST) ?
+ SR_NOTIFY_MCUACCUM : 0;
+ val |= (status & ERRCONFIG_MCUVALIDINTEN) ?
+ SR_NOTIFY_MCUVALID : 0;
+ val |= (status & ERRCONFIG_MCUBOUNDINTEN) ?
+ SR_NOTIFY_MCUBOUND : 0;
+ val |= (status & ERRCONFIG_MCUDISACKINTEN) ?
+ SR_NOTIFY_MCUDISACK : 0;
+
+ return val;
+}
+
+static inline u8 irqstat_to_notifier_v2(u32 status)
+{
+ u8 val;
+
+ val = (status & IRQENABLE_MCUACCUMINT) ?
+ SR_NOTIFY_MCUACCUM : 0;
+ val |= (status & IRQENABLE_MCUVALIDINT) ?
+ SR_NOTIFY_MCUVALID : 0;
+ val |= (status & IRQENABLE_MCUBOUNDSINT) ?
+ SR_NOTIFY_MCUBOUND : 0;
+ val |= (status & IRQENABLE_MCUDISABLEACKINT) ?
+ SR_NOTIFY_MCUDISACK : 0;
+
+ return val;
+}
+
+
static irqreturn_t sr_interrupt(int irq, void *data)
{
struct omap_sr *sr_info = (struct omap_sr *)data;
u32 status = 0;
+ u32 value = 0;
if (sr_info->ip_type == SR_TYPE_V1) {
+ /* Status bits are one bit before enable bits in v1 */
+ value = notifier_to_irqen_v1(sr_class->notify_flags) >> 1;
+
/* Read the status bits */
status = sr_read_reg(sr_info, ERRCONFIG_V1);
+ status &= value;
/* Clear them by writing back */
- sr_write_reg(sr_info, ERRCONFIG_V1, status);
+ sr_modify_reg(sr_info, ERRCONFIG_V1, value, status);
+
+ value = irqstat_to_notifier_v1(status);
} else if (sr_info->ip_type == SR_TYPE_V2) {
+ value = notifier_to_irqen_v2(sr_class->notify_flags);
/* Read the status bits */
status = sr_read_reg(sr_info, IRQSTATUS);
+ status &= value;
/* Clear them by writing back */
sr_write_reg(sr_info, IRQSTATUS, status);
+ value = irqstat_to_notifier_v2(status);
}
- if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
- sr_class->notify(sr_info->voltdm, status);
+ /* Attempt some resemblance of recovery! */
+ if (!value) {
+ dev_err(&sr_info->pdev->dev, "%s: Spurious interrupt!"
+ "status = 0x%08x. Disabling to prevent spamming!!\n",
+ __func__, status);
+ disable_irq_nosync(sr_info->irq);
+ sr_info->irq_enabled = false;
+ } else {
+ /* If the caller reports inability to handle, disable as well */
+ if (sr_class->notify && sr_class->notify(sr_info->voltdm,
+ sr_info->voltdm_cdata, value)) {
+ dev_err(&sr_info->pdev->dev, "%s: Callback cant handle!"
+ "status=0x%08x. Disabling to prevent spam!!\n",
+ __func__, status);
+ disable_irq_nosync(sr_info->irq);
+ sr_info->irq_enabled = false;
+ }
+
+ }
return IRQ_HANDLED;
}
@@ -214,6 +306,7 @@ static void sr_set_regfields(struct omap_sr *sr)
static void sr_start_vddautocomp(struct omap_sr *sr)
{
+ int r;
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
dev_warn(&sr->pdev->dev,
"%s: smartreflex class driver not registered\n",
@@ -221,8 +314,23 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
return;
}
- if (!sr_class->enable(sr->voltdm))
+ /* pause dvfs from interfereing with our operations */
+ mutex_lock(&omap_dvfs_lock);
+
+ if (sr_class->init &&
+ sr_class->init(sr->voltdm, &sr->voltdm_cdata,
+ sr_class->class_priv_data)) {
+ dev_err(&sr->pdev->dev,
+ "%s: SRClass initialization failed\n", __func__);
+ mutex_unlock(&omap_dvfs_lock);
+ return;
+ }
+
+ r = sr_class->enable(sr->voltdm, sr->voltdm_cdata,
+ omap_voltage_get_curr_vdata(sr->voltdm));
+ if (!r)
sr->autocomp_active = true;
+ mutex_unlock(&omap_dvfs_lock);
}
static void sr_stop_vddautocomp(struct omap_sr *sr)
@@ -235,8 +343,19 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
}
if (sr->autocomp_active) {
- sr_class->disable(sr->voltdm, 1);
+ /* Pause dvfs from interfereing with our operations */
+ mutex_lock(&omap_dvfs_lock);
+ sr_class->disable(sr->voltdm, sr->voltdm_cdata,
+ omap_voltage_get_curr_vdata(sr->voltdm), 1);
+ if (sr_class->deinit &&
+ sr_class->deinit(sr->voltdm, &sr->voltdm_cdata,
+ sr_class->class_priv_data)) {
+ dev_err(&sr->pdev->dev,
+ "%s: SR[%d]Class deinitialization failed\n",
+ __func__, sr->srid);
+ }
sr->autocomp_active = false;
+ mutex_unlock(&omap_dvfs_lock);
}
}
@@ -258,9 +377,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 +387,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,21 +396,23 @@ 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)
{
int timeout = 0;
+ int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
+ ERRCONFIG_MCUBOUNDINTST;
/* Enable MCUDisableAcknowledge interrupt */
sr_modify_reg(sr, ERRCONFIG_V1,
@@ -301,13 +421,13 @@ static void sr_v1_disable(struct omap_sr *sr)
/* SRCONFIG - disable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
- /* Disable all other SR interrupts and clear the status */
+ /* Disable all other SR interrupts and clear the status as needed */
+ if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1)
+ errconf_val |= ERRCONFIG_VPBOUNDINTST_V1;
sr_modify_reg(sr, ERRCONFIG_V1,
(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
- (ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
- ERRCONFIG_MCUBOUNDINTST |
- ERRCONFIG_VPBOUNDINTST_V1));
+ errconf_val);
/*
* Wait for SR to be disabled.
@@ -336,15 +456,23 @@ static void sr_v2_disable(struct omap_sr *sr)
/* SRCONFIG - disable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
- /* Disable all other SR interrupts and clear the status */
- sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+ /*
+ * Disable all other SR interrupts and clear the status
+ * write to status register ONLY on need basis - only if status
+ * is set.
+ */
+ if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2)
+ sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
ERRCONFIG_VPBOUNDINTST_V2);
- sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
- IRQENABLE_MCUVALIDINT |
- IRQENABLE_MCUBOUNDSINT));
+ else
+ sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+ 0x0);
sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
IRQSTATUS_MCVALIDINT |
IRQSTATUS_MCBOUNDSINT));
+ sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
+ IRQENABLE_MCUVALIDINT |
+ IRQENABLE_MCUBOUNDSINT));
/*
* Wait for SR to be disabled.
@@ -359,8 +487,8 @@ static void sr_v2_disable(struct omap_sr *sr)
__func__);
/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
- sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
+ sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
}
static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
@@ -384,6 +512,28 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
/* Public Functions */
/**
+ * is_sr_enabled() - is Smart reflex enabled for this domain?
+ * @voltdm: voltage domain to check
+ *
+ * Returns 0 if SR is enabled for this domain, else returns err
+ */
+bool is_sr_enabled(struct voltagedomain *voltdm)
+{
+ struct omap_sr *sr;
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_warning("%s: invalid param voltdm\n", __func__);
+ return false;
+ }
+ sr = _sr_lookup(voltdm);
+ if (IS_ERR(sr)) {
+ pr_warning("%s: omap_sr struct for sr_%s not found\n",
+ __func__, voltdm->name);
+ return false;
+ }
+ return sr->autocomp_active;
+}
+
+/**
* sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
* error generator module.
* @voltdm: VDD pointer to which the SR module to be configured belongs to.
@@ -446,8 +596,52 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
sr_errconfig);
/* Enabling the interrupts if the ERROR module is used */
- sr_modify_reg(sr, errconfig_offs,
- vpboundint_en, (vpboundint_en | vpboundint_st));
+ sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st),
+ vpboundint_en);
+
+ return 0;
+}
+
+/**
+ * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
+ * @voltdm: voltagedomain pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable the error generator module inside the smartreflex module.
+ *
+ * Returns 0 on success and error value in case of failure.
+ */
+int sr_disable_errgen(struct voltagedomain *voltdm)
+{
+ u32 errconfig_offs, vpboundint_en;
+ u32 vpboundint_st;
+ struct omap_sr *sr = _sr_lookup(voltdm);
+
+ if (IS_ERR(sr)) {
+ pr_warning("%s: omap_sr struct for sr_%s not found\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ if (sr->ip_type == SR_TYPE_V1) {
+ errconfig_offs = ERRCONFIG_V1;
+ vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+ vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+ } else if (sr->ip_type == SR_TYPE_V2) {
+ errconfig_offs = ERRCONFIG_V2;
+ vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+ vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+ } else {
+ dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+ "module without specifying the ip\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Disable the interrupts of ERROR module */
+ sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
+
+ /* Disable the Sensor and errorgen */
+ sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0);
return 0;
}
@@ -532,7 +726,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
/**
* sr_enable() - Enables the smartreflex module.
* @voltdm: VDD pointer to which the SR module to be configured belongs to.
- * @volt: The voltage at which the Voltage domain associated with
+ * @volt_data: The voltage at which the Voltage domain associated with
* the smartreflex module is operating at.
* This is required only to program the correct Ntarget value.
*
@@ -540,10 +734,9 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
* enable a smartreflex module. Returns 0 on success. Returns error
* value if the voltage passed is wrong or if ntarget value is wrong.
*/
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
+int sr_enable(struct voltagedomain *voltdm, struct omap_volt_data *volt_data)
{
u32 nvalue_reciprocal;
- struct omap_volt_data *volt_data;
struct omap_sr *sr = _sr_lookup(voltdm);
int ret;
@@ -553,19 +746,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
return -EINVAL;
}
- volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
-
- if (IS_ERR(volt_data)) {
- dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
- "for nominal voltage %ld\n", __func__, volt);
- return -ENODATA;
+ if (IS_ERR_OR_NULL(volt_data)) {
+ dev_warn(&sr->pdev->dev, "%s: bad voltage data\n", __func__);
+ return -EINVAL;
}
nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
if (!nvalue_reciprocal) {
dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
- __func__, volt);
+ __func__, omap_get_operation_voltage(volt_data));
return -ENODATA;
}
@@ -579,7 +769,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
return 0;
/* Configure SR */
- ret = sr_class->configure(voltdm);
+ ret = sr_class->configure(voltdm, sr->voltdm_cdata);
if (ret)
return ret;
@@ -622,7 +812,79 @@ void sr_disable(struct voltagedomain *voltdm)
sr_v2_disable(sr);
}
- pm_runtime_put_sync(&sr->pdev->dev);
+ pm_runtime_put_sync_suspend(&sr->pdev->dev);
+}
+
+/**
+ * sr_notifier_control() - control the notifier mechanism
+ * @voltdm: VDD pointer to which the SR module to be configured belongs to.
+ * @enable: true to enable notifiers and false to disable the same
+ *
+ * SR modules allow an MCU interrupt mechanism that vary based on the IP
+ * revision, we allow the system to generate interrupt if the class driver
+ * has capability to handle the same. it is upto the class driver to ensure
+ * the proper sequencing and handling for a clean implementation. returns
+ * 0 if all goes fine, else returns failure results
+ */
+int sr_notifier_control(struct voltagedomain *voltdm, bool enable)
+{
+ struct omap_sr *sr = _sr_lookup(voltdm);
+ u32 value = 0;
+
+ if (!sr) {
+ pr_warning("%s: sr corresponding to domain not found\n",
+ __func__);
+ return -EINVAL;
+ }
+ if (!sr->autocomp_active)
+ return -EINVAL;
+
+ /* If I could never register an ISR, why bother?? */
+ if (!(sr_class && sr_class->notify && sr_class->notify_flags &&
+ sr->irq)) {
+ dev_warn(&sr->pdev->dev,
+ "%s: unable to setup IRQ without handling mechanism\n",
+ __func__);
+ return -EINVAL;
+ }
+
+
+ switch (sr->ip_type) {
+ case SR_TYPE_V1:
+ value = notifier_to_irqen_v1(sr_class->notify_flags);
+ break;
+ case SR_TYPE_V2:
+ value = notifier_to_irqen_v2(sr_class->notify_flags);
+ break;
+ default:
+ dev_warn(&sr->pdev->dev, "%s: unknown type of sr??\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (!enable)
+ sr_write_reg(sr, IRQSTATUS, value);
+
+ switch (sr->ip_type) {
+ case SR_TYPE_V1:
+ sr_modify_reg(sr, ERRCONFIG_V1, value,
+ (enable) ? value : 0);
+ break;
+ case SR_TYPE_V2:
+ sr_write_reg(sr, (enable) ? IRQENABLE_SET : IRQENABLE_CLR,
+ value);
+ break;
+ }
+
+ if (enable != sr->irq_enabled) {
+ if (enable)
+ enable_irq(sr->irq);
+ else
+ disable_irq(sr->irq);
+ sr->irq_enabled = enable;
+ }
+
+ return 0;
}
/**
@@ -665,13 +927,15 @@ int sr_register_class(struct omap_sr_class_data *class_data)
* omap_sr_enable() - API to enable SR clocks and to call into the
* registered smartreflex class enable API.
* @voltdm: VDD pointer to which the SR module to be configured belongs to.
+ * @volt_data: Voltage data to go to
*
* This API is to be called from the kernel in order to enable
* a particular smartreflex module. This API will do the initial
* configurations to turn on the smartreflex module and in turn call
* into the registered smartreflex class enable API.
*/
-void omap_sr_enable(struct voltagedomain *voltdm)
+void omap_sr_enable(struct voltagedomain *voltdm,
+ struct omap_volt_data *volt_data)
{
struct omap_sr *sr = _sr_lookup(voltdm);
@@ -690,7 +954,8 @@ void omap_sr_enable(struct voltagedomain *voltdm)
return;
}
- sr_class->enable(voltdm);
+ sr_class->enable(voltdm, sr->voltdm_cdata,
+ omap_voltage_get_curr_vdata(voltdm));
}
/**
@@ -723,7 +988,8 @@ void omap_sr_disable(struct voltagedomain *voltdm)
return;
}
- sr_class->disable(voltdm, 0);
+ sr_class->disable(voltdm, sr->voltdm_cdata,
+ omap_voltage_get_curr_vdata(voltdm), 0);
}
/**
@@ -736,27 +1002,30 @@ void omap_sr_disable(struct voltagedomain *voltdm)
* into the registered smartreflex class disable API. This API will tell
* the smartreflex class disable to reset the VP voltage after
* disabling smartreflex.
+ *
+ * Returns result of transition request.
*/
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
+int omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
{
struct omap_sr *sr = _sr_lookup(voltdm);
if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for sr_%s not found\n",
__func__, voltdm->name);
- return;
+ return -ENODEV;
}
if (!sr->autocomp_active)
- return;
+ return 0;
if (!sr_class || !(sr_class->disable)) {
dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
"registered\n", __func__);
- return;
+ return -ENODEV;
}
- sr_class->disable(voltdm, 1);
+ return sr_class->disable(voltdm, sr->voltdm_cdata,
+ omap_voltage_get_curr_vdata(voltdm), 1);
}
/**
@@ -808,10 +1077,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 +1096,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",
@@ -858,6 +1131,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
pm_runtime_enable(&pdev->dev);
+ pm_runtime_irq_safe(&pdev->dev);
sr_info->pdev = pdev;
sr_info->srid = pdev->id;
@@ -891,23 +1165,30 @@ static int __init omap_sr_probe(struct platform_device *pdev)
ret = sr_late_init(sr_info);
if (ret) {
pr_warning("%s: Error in SR late init\n", __func__);
- return ret;
+ goto err_iounmap;
}
}
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__);
@@ -998,8 +1279,32 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
return 0;
}
+static void __devexit omap_sr_shutdown(struct platform_device *pdev)
+{
+ struct omap_sr_data *pdata = pdev->dev.platform_data;
+ struct omap_sr *sr_info;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+ return;
+ }
+
+ sr_info = _sr_lookup(pdata->voltdm);
+ if (IS_ERR(sr_info)) {
+ dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+ __func__);
+ return;
+ }
+
+ if (sr_info->autocomp_active)
+ sr_stop_vddautocomp(sr_info);
+
+ return;
+}
+
static struct platform_driver smartreflex_driver = {
.remove = omap_sr_remove,
+ .shutdown = omap_sr_shutdown,
.driver = {
.name = "smartreflex",
},
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 5f35b9e..f17c2ec 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -142,6 +142,12 @@
#define OMAP3430_SR_ERRWEIGHT 0x04
#define OMAP3430_SR_ERRMAXLIMIT 0x02
+/* Smart reflex notifiers for class drivers to use */
+#define SR_NOTIFY_MCUDISACK BIT(3)
+#define SR_NOTIFY_MCUBOUND BIT(2)
+#define SR_NOTIFY_MCUVALID BIT(1)
+#define SR_NOTIFY_MCUACCUM BIT(0)
+
/**
* struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
* pmic specific info to smartreflex driver
@@ -152,6 +158,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.
@@ -162,12 +177,15 @@ struct omap_sr_pmic_data {
#define SR_CLASS1 0x1
#define SR_CLASS2 0x2
#define SR_CLASS3 0x3
+#define SR_CLASS1P5 0x4
/**
* struct omap_sr_class_data - Smartreflex class driver info
*
* @enable: API to enable a particular class smaartreflex.
* @disable: API to disable a particular class smartreflex.
+ * @init: API to do class specific initialization (optional)
+ * @deinit: API to do class specific deinitialization (optional)
* @configure: API to configure a particular class smartreflex.
* @notify: API to notify the class driver about an event in SR.
* Not needed for class3.
@@ -175,14 +193,23 @@ struct omap_sr_pmic_data {
* @class_type: specify which smartreflex class.
* Can be used by the SR driver to take any class
* based decisions.
+ * @class_priv_data: Class specific private data (optional)
*/
struct omap_sr_class_data {
- int (*enable)(struct voltagedomain *voltdm);
- int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
- int (*configure)(struct voltagedomain *voltdm);
- int (*notify)(struct voltagedomain *voltdm, u32 status);
+ int (*enable)(struct voltagedomain *voltdm, void *voltdm_cdata,
+ struct omap_volt_data *volt_data);
+ int (*disable)(struct voltagedomain *voltdm, void *voltdm_cdata,
+ struct omap_volt_data *volt_data, int is_volt_reset);
+ int (*init)(struct voltagedomain *voltdm, void **voltdm_cdata,
+ void *class_priv_data);
+ int (*deinit)(struct voltagedomain *voltdm, void **voltdm_cdata,
+ void *class_priv_data);
+ int (*configure)(struct voltagedomain *voltdm, void *voltdm_cdata);
+ int (*notify)(struct voltagedomain *voltdm, void *voltdm_cdata,
+ u32 status);
u8 notify_flags;
u8 class_type;
+ void *class_priv_data;
};
/**
@@ -220,27 +247,43 @@ struct omap_sr_data {
};
/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_enable(struct voltagedomain *voltdm,
+ struct omap_volt_data *volt_data);
void omap_sr_disable(struct voltagedomain *voltdm);
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+int omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
/* API to register the pmic specific data with the smartreflex driver. */
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
/* Smartreflex driver hooks to be called from Smartreflex class driver */
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+int sr_enable(struct voltagedomain *voltdm, struct omap_volt_data *volt_data);
void sr_disable(struct voltagedomain *voltdm);
+int sr_notifier_control(struct voltagedomain *voltdm, bool enable);
int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_disable_errgen(struct voltagedomain *voltdm);
int sr_configure_minmax(struct voltagedomain *voltdm);
/* API to register the smartreflex class driver with the smartreflex driver */
int sr_register_class(struct omap_sr_class_data *class_data);
+bool is_sr_enabled(struct voltagedomain *voltdm);
#else
static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable_reset_volt(
- struct voltagedomain *voltdm) {}
+
+static inline int sr_notifier_control(struct voltagedomain *voltdm,
+ bool enable)
+{
+ return -EINVAL;
+}
+
+static inline int omap_sr_disable_reset_volt(
+ struct voltagedomain *voltdm) { return 0; }
static inline void omap_sr_register_pmic(
struct omap_sr_pmic_data *pmic_data) {}
+static inline bool is_sr_enabled(struct voltagedomain *voltdm)
+{
+ return false;
+}
#endif
+
#endif
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/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
new file mode 100644
index 0000000..0a647a3
--- /dev/null
+++ b/arch/arm/mach-omap2/temp_sensor_device.c
@@ -0,0 +1,95 @@
+/*
+ * OMAP on die Temperature sensor device file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <plat/omap_device.h>
+#include "control.h"
+#include "pm.h"
+#include <plat/temperature_sensor.h>
+
+void omap_temp_sensor_resume_idle(void)
+{
+ omap_temp_sensor_idle(0);
+}
+
+void omap_temp_sensor_prepare_idle(void)
+{
+ omap_temp_sensor_idle(1);
+}
+
+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ }
+};
+
+static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
+{
+ struct omap_temp_sensor_pdata *temp_sensor_pdata;
+ struct omap_device *od;
+ static int i;
+ int ret = 0;
+
+ temp_sensor_pdata =
+ kzalloc(sizeof(struct omap_temp_sensor_pdata), GFP_KERNEL);
+ if (!temp_sensor_pdata) {
+ pr_err
+ ("%s: Unable to allocate memory for %s.Error!\n",
+ __func__, oh->name);
+ return -ENOMEM;
+ }
+
+ temp_sensor_pdata->offset = OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR;
+
+ temp_sensor_pdata->name = "omap_temp_sensor";
+
+ od = omap_device_build(temp_sensor_pdata->name, i, oh, temp_sensor_pdata,
+ sizeof(*temp_sensor_pdata),
+ omap_temp_sensor_latency,
+ ARRAY_SIZE(omap_temp_sensor_latency), 0);
+ if (IS_ERR(od)) {
+ pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
+ __func__, temp_sensor_pdata->name, oh->name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ i++;
+done:
+ kfree(temp_sensor_pdata);
+ return ret;
+}
+
+int __init omap_devinit_temp_sensor(void)
+{
+ if (!cpu_is_omap446x())
+ return 0;
+
+ return omap_hwmod_for_each_by_class("thermal_sensor",
+ temp_sensor_dev_init, NULL);
+}
+
+arch_initcall(omap_devinit_temp_sensor);
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 3b9cf85..69a5e00 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -44,7 +44,7 @@
#include <plat/omap_hwmod.h>
#include "timer-gp.h"
-
+#include "dmtimer.h"
/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
#define MAX_GPTIMER_ID 12
@@ -106,6 +106,7 @@ static struct clock_event_device clockevent_gpt = {
.name = "gp timer",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
+ .rating = 300,
.set_next_event = omap2_gp_timer_set_next_event,
.set_mode = omap2_gp_timer_set_mode,
};
@@ -134,13 +135,9 @@ static void __init omap2_gp_clockevent_init(void)
{
u32 tick_rate;
int src;
- char clockevent_hwmod_name[8]; /* 8 = sizeof("timerXX0") */
inited = 1;
- sprintf(clockevent_hwmod_name, "timer%d", gptimer_id);
- omap_hwmod_setup_one(clockevent_hwmod_name);
-
gptimer = omap_dm_timer_request_specific(gptimer_id);
BUG_ON(gptimer == NULL);
gptimer_wakeup = gptimer;
@@ -154,8 +151,8 @@ static void __init omap2_gp_clockevent_init(void)
#endif
if (gptimer_id != 12)
- WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)),
- "timer-gp: omap_dm_timer_set_source() failed\n");
+ WARN(IS_ERR_VALUE(omap2_system_timer_set_src(gptimer, src)),
+ "timer-gp: omap2_system_timer_set_src() failed\n");
tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
@@ -174,7 +171,8 @@ static void __init omap2_gp_clockevent_init(void)
clockevent_delta2ns(3, &clockevent_gpt);
/* Timer internal resynch latency. */
- clockevent_gpt.cpumask = cpumask_of(0);
+ clockevent_gpt.cpumask = cpu_all_mask;
+ clockevent_gpt.irq = omap_dm_timer_get_irq(gptimer);
clockevents_register_device(&clockevent_gpt);
}
@@ -255,7 +253,7 @@ static void __init omap2_gp_timer_init(void)
BUG_ON(!twd_base);
}
#endif
- omap_dm_timer_init();
+ omap2_system_timer_init(gptimer_id);
omap2_gp_clockevent_init();
omap2_gp_clocksource_init();
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index 89ae298..7b422b5 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -22,58 +22,433 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <plat/usb.h>
+#include <plat/omap_device.h>
#include "mux.h"
#ifdef CONFIG_MFD_OMAP_USB_HOST
-#define OMAP_USBHS_DEVICE "usbhs-omap"
+#define OMAP_USBHS_DEVICE "usbhs_omap"
+#define USBHS_UHH_HWMODNAME "usbhs_uhh"
+#define USBHS_OHCI_HWMODNAME "usbhs_ohci"
+#define USBHS_EHCI_HWMODNAME "usbhs_ehci"
+#define USBHS_TLL_HWMODNAME "usbhs_tll"
-static struct resource usbhs_resources[] = {
+static struct usbhs_omap_platform_data usbhs_data;
+static struct ehci_hcd_omap_platform_data ehci_data;
+static struct ohci_hcd_omap_platform_data ohci_data;
+
+static struct omap_device_pm_latency omap_uhhtll_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+static struct usbhs_wakeup {
+ struct device *dev;
+ struct omap_hwmod *oh_ehci;
+ struct omap_hwmod *oh_ohci;
+ struct work_struct wakeup_work;
+ int wakeup_ehci:1;
+ int wakeup_ohci:1;
+} *usbhs_wake;
+
+/* MUX settings for EHCI pins */
+static struct omap_device_pad port1_phy_pads[] __initdata = {
{
- .name = "uhh",
- .flags = IORESOURCE_MEM,
+ .name = "usbb1_ulpitll_stp.usbb1_ulpiphy_stp",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE4,
},
{
- .name = "tll",
- .flags = IORESOURCE_MEM,
+ .name = "usbb1_ulpitll_clk.usbb1_ulpiphy_clk",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
},
{
- .name = "ehci",
- .flags = IORESOURCE_MEM,
+ .name = "usbb1_ulpitll_dir.usbb1_ulpiphy_dir",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~OMAP_WAKEUP_EN,
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
},
{
- .name = "ehci-irq",
- .flags = IORESOURCE_IRQ,
+ .name = "usbb1_ulpitll_nxt.usbb1_ulpiphy_nxt",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
},
{
- .name = "ohci",
- .flags = IORESOURCE_MEM,
+ .name = "usbb1_ulpitll_dat0.usbb1_ulpiphy_dat0",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~OMAP_WAKEUP_EN,
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
},
{
- .name = "ohci-irq",
- .flags = IORESOURCE_IRQ,
- }
+ .name = "usbb1_ulpitll_dat1.usbb1_ulpiphy_dat1",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb1_ulpitll_dat2.usbb1_ulpiphy_dat2",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb1_ulpitll_dat3.usbb1_ulpiphy_dat3",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb1_ulpitll_dat4.usbb1_ulpiphy_dat4",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb1_ulpitll_dat5.usbb1_ulpiphy_dat5",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb1_ulpitll_dat6.usbb1_ulpiphy_dat6",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb1_ulpitll_dat7.usbb1_ulpiphy_dat7",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
};
-static struct platform_device usbhs_device = {
- .name = OMAP_USBHS_DEVICE,
- .id = 0,
- .num_resources = ARRAY_SIZE(usbhs_resources),
- .resource = usbhs_resources,
+static struct omap_device_pad port1_tll_pads[] __initdata = {
+ {
+ .name = "usbb1_ulpitll_stp.usbb1_ulpitll_stp",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_clk.usbb1_ulpitll_clk",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dir.usbb1_ulpitll_dir",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_nxt.usbb1_ulpitll_nxt",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat0.usbb1_ulpitll_dat0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat1.usbb1_ulpitll_dat1",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat2.usbb1_ulpitll_dat2",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat3.usbb1_ulpitll_dat3",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat4.usbb1_ulpitll_dat4",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat5.usbb1_ulpitll_dat5",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat6.usbb1_ulpitll_dat6",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb1_ulpitll_dat7.usbb1_ulpitll_dat7",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
};
-static struct usbhs_omap_platform_data usbhs_data;
-static struct ehci_hcd_omap_platform_data ehci_data;
-static struct ohci_hcd_omap_platform_data ohci_data;
+static struct omap_device_pad port2_phy_pads[] __initdata = {
+ {
+ .name = "usbb2_ulpitll_stp.usbb2_ulpiphy_stp",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_clk.usbb2_ulpiphy_clk",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dir.usbb2_ulpiphy_dir",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_WAKEUP_EN
+ | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_nxt.usbb2_ulpiphy_nxt",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat0.usbb2_ulpiphy_dat0",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_WAKEUP_EN
+ | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat1.usbb2_ulpiphy_dat1",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat2.usbb2_ulpiphy_dat2",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat3.usbb2_ulpiphy_dat3",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat4.usbb2_ulpiphy_dat4",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat5.usbb2_ulpiphy_dat5",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat6.usbb2_ulpiphy_dat6",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "usbb2_ulpitll_dat7.usbb2_ulpiphy_dat7",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+};
-/* MUX settings for EHCI pins */
+static struct omap_device_pad port2_tll_pads[] __initdata = {
+ {
+ .name = "usbb2_ulpitll_stp.usbb2_ulpitll_stp",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_clk.usbb2_ulpitll_clk",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dir.usbb2_ulpitll_dir",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_nxt.usbb2_ulpitll_nxt",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat0.usbb2_ulpitll_dat0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat1.usbb2_ulpitll_dat1",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat2.usbb2_ulpitll_dat2",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat3.usbb2_ulpitll_dat3",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat4.usbb2_ulpitll_dat4",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat5.usbb2_ulpitll_dat5",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat6.usbb2_ulpitll_dat6",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "usbb2_ulpitll_dat7.usbb2_ulpitll_dat7",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad port1_6pin_pads[] __initdata = {
+ {
+ .name = "usbb1_ulpitll_stp.usbb1_mm_rxdp",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_nxt.usbb1_mm_rxdm",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat0.usbb1_mm_rxrcv",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat3.usbb1_mm_txen",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat1.usbb1_mm_txdat",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat2.usbb1_mm_txse0",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+};
+
+static struct omap_device_pad port1_4pin_pads[] __initdata = {
+ {
+ .name = "usbb1_ulpitll_dat0.usbb1_mm_rxrcv",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat3.usbb1_mm_txen",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat1.usbb1_mm_txdat",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat2.usbb1_mm_txse0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+};
+
+static struct omap_device_pad port1_3pin_pads[] __initdata = {
+ {
+ .name = "usbb1_ulpitll_dat3.usbb1_mm_txen",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat1.usbb1_mm_txdat",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat2.usbb1_mm_txse0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+};
+
+static struct omap_device_pad port1_2pin_pads[] __initdata = {
+ {
+ .name = "usbb1_ulpitll_dat1.usbb1_mm_txdat",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+ {
+ .name = "usbb1_ulpitll_dat2.usbb1_mm_txse0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE5,
+ },
+};
+
+static struct omap_device_pad port2_6pin_pads[] __initdata = {
+ {
+ .name = "abe_mcbsp2_dr.usbb2_mm_rxdp",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_mcbsp2_clkx.usbb2_mm_rxdm",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_mcbsp2_dx.usbb2_mm_rxrcv",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_mcbsp2_fsx.usbb2_mm_txen",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_din1.usbb2_mm_txdat",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_clk1.usbb2_mm_txse0",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = (OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4) & ~(OMAP_WAKEUP_EN),
+ .idle = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+};
+
+static struct omap_device_pad port2_4pin_pads[] __initdata = {
+ {
+ .name = "abe_mcbsp2_dx.usbb2_mm_rxrcv",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_mcbsp2_fsx.usbb2_mm_txen",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_din1.usbb2_mm_txdat",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_clk1.usbb2_mm_txse0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+};
+
+static struct omap_device_pad port2_3pin_pads[] __initdata = {
+ {
+ .name = "abe_mcbsp2_fsx.usbb2_mm_txen",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_din1.usbb2_mm_txdat",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_clk1.usbb2_mm_txse0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+};
+
+static struct omap_device_pad port2_2pin_pads[] __initdata = {
+ {
+ .name = "abe_mcbsp2_fsx.usbb2_mm_txen",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_din1.usbb2_mm_txdat",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+ {
+ .name = "abe_dmic_clk1.usbb2_mm_txse0",
+ .enable = OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE4,
+ },
+};
/*
* setup_ehci_io_mux - initialize IO pad mux for USBHOST
*/
@@ -220,60 +595,20 @@ static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
return;
}
-static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static struct omap_hwmod_mux_info *
+setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
{
+ struct omap_device_pad *pads;
+ int pads_cnt;
+
switch (port_mode[0]) {
case OMAP_EHCI_PORT_MODE_PHY:
- omap_mux_init_signal("usbb1_ulpiphy_stp",
- OMAP_PIN_OUTPUT);
- omap_mux_init_signal("usbb1_ulpiphy_clk",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dir",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_nxt",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat0",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat1",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat2",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat3",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat4",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat5",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat6",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpiphy_dat7",
- OMAP_PIN_INPUT_PULLDOWN);
+ pads = port1_phy_pads;
+ pads_cnt = ARRAY_SIZE(port1_phy_pads);
break;
case OMAP_EHCI_PORT_MODE_TLL:
- omap_mux_init_signal("usbb1_ulpitll_stp",
- OMAP_PIN_INPUT_PULLUP);
- omap_mux_init_signal("usbb1_ulpitll_clk",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dir",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_nxt",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat0",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat1",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat2",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat3",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat4",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat5",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat6",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_ulpitll_dat7",
- OMAP_PIN_INPUT_PULLDOWN);
+ pads = port1_tll_pads;
+ pads_cnt = ARRAY_SIZE(port1_tll_pads);
break;
case OMAP_USBHS_PORT_MODE_UNUSED:
default:
@@ -281,61 +616,19 @@ static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
}
switch (port_mode[1]) {
case OMAP_EHCI_PORT_MODE_PHY:
- omap_mux_init_signal("usbb2_ulpiphy_stp",
- OMAP_PIN_OUTPUT);
- omap_mux_init_signal("usbb2_ulpiphy_clk",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dir",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_nxt",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat0",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat1",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat2",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat3",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat4",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat5",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat6",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpiphy_dat7",
- OMAP_PIN_INPUT_PULLDOWN);
+ pads = port2_phy_pads;
+ pads_cnt = ARRAY_SIZE(port2_phy_pads);
break;
case OMAP_EHCI_PORT_MODE_TLL:
- omap_mux_init_signal("usbb2_ulpitll_stp",
- OMAP_PIN_INPUT_PULLUP);
- omap_mux_init_signal("usbb2_ulpitll_clk",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dir",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_nxt",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat0",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat1",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat2",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat3",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat4",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat5",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat6",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_ulpitll_dat7",
- OMAP_PIN_INPUT_PULLDOWN);
+ pads = port2_tll_pads;
+ pads_cnt = ARRAY_SIZE(port2_tll_pads);
break;
case OMAP_USBHS_PORT_MODE_UNUSED:
default:
break;
}
+
+ return omap_hwmod_mux_init(pads, pads_cnt);
}
static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
@@ -435,37 +728,35 @@ static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
}
}
-static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static struct omap_hwmod_mux_info *
+setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
{
+ struct omap_device_pad *pads;
+ int pads_cnt;
+
switch (port_mode[0]) {
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
- omap_mux_init_signal("usbb1_mm_rxdp",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_mm_rxdm",
- OMAP_PIN_INPUT_PULLDOWN);
-
+ pads = port1_6pin_pads;
+ pads_cnt = ARRAY_SIZE(port1_6pin_pads);
+ break;
case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
- omap_mux_init_signal("usbb1_mm_rxrcv",
- OMAP_PIN_INPUT_PULLDOWN);
-
+ pads = port1_4pin_pads;
+ pads_cnt = ARRAY_SIZE(port1_4pin_pads);
+ break;
case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
- omap_mux_init_signal("usbb1_mm_txen",
- OMAP_PIN_INPUT_PULLDOWN);
-
-
+ pads = port1_3pin_pads;
+ pads_cnt = ARRAY_SIZE(port1_3pin_pads);
+ break;
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
- omap_mux_init_signal("usbb1_mm_txdat",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb1_mm_txse0",
- OMAP_PIN_INPUT_PULLDOWN);
+ pads = port1_2pin_pads;
+ pads_cnt = ARRAY_SIZE(port1_2pin_pads);
break;
-
case OMAP_USBHS_PORT_MODE_UNUSED:
default:
break;
@@ -476,39 +767,79 @@ static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
- omap_mux_init_signal("usbb2_mm_rxdp",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_mm_rxdm",
- OMAP_PIN_INPUT_PULLDOWN);
-
+ pads = port2_6pin_pads;
+ pads_cnt = ARRAY_SIZE(port2_6pin_pads);
+ break;
case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
- omap_mux_init_signal("usbb2_mm_rxrcv",
- OMAP_PIN_INPUT_PULLDOWN);
-
+ pads = port2_4pin_pads;
+ pads_cnt = ARRAY_SIZE(port2_4pin_pads);
+ break;
case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
- omap_mux_init_signal("usbb2_mm_txen",
- OMAP_PIN_INPUT_PULLDOWN);
-
-
+ pads = port2_3pin_pads;
+ pads_cnt = ARRAY_SIZE(port2_3pin_pads);
+ break;
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
- omap_mux_init_signal("usbb2_mm_txdat",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("usbb2_mm_txse0",
- OMAP_PIN_INPUT_PULLDOWN);
+ pads = port2_2pin_pads;
+ pads_cnt = ARRAY_SIZE(port2_3pin_pads);
break;
-
case OMAP_USBHS_PORT_MODE_UNUSED:
default:
break;
}
+
+ return omap_hwmod_mux_init(pads, pads_cnt);
+}
+
+void usbhs_wakeup()
+{
+ int workq = 0;
+
+ if (!usbhs_wake)
+ return;
+
+ if (test_bit(USB_OHCI_LOADED, &usb_hcds_loaded) &&
+ omap_hwmod_pad_get_wakeup_status(usbhs_wake->oh_ohci)) {
+ usbhs_wake->wakeup_ohci = 1;
+ workq = 1;
+ }
+
+ if (test_bit(USB_EHCI_LOADED, &usb_hcds_loaded) &&
+ omap_hwmod_pad_get_wakeup_status(usbhs_wake->oh_ehci)) {
+ usbhs_wake->wakeup_ehci = 1;
+ workq = 1;
+ }
+
+ if (workq)
+ queue_work(pm_wq, &usbhs_wake->wakeup_work);
+}
+
+static void usbhs_resume_work(struct work_struct *work)
+{
+ dev_dbg(usbhs_wake->dev, "USB IO PAD Wakeup event triggered\n");
+
+ if (usbhs_wake->wakeup_ehci) {
+ usbhs_wake->wakeup_ehci = 0;
+ omap_hwmod_disable_ioring_wakeup(usbhs_wake->oh_ehci);
+ }
+
+ if (usbhs_wake->wakeup_ohci) {
+ usbhs_wake->wakeup_ohci = 0;
+ omap_hwmod_disable_ioring_wakeup(usbhs_wake->oh_ohci);
+ }
+
+ pm_runtime_get_sync(usbhs_wake->dev);
+ pm_runtime_put_sync(usbhs_wake->dev);
}
void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
{
- int i;
+ struct omap_hwmod *oh[4];
+ struct omap_device *od;
+ int bus_id = -1;
+ int i;
for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
usbhs_data.port_mode[i] = pdata->port_mode[i];
@@ -516,55 +847,74 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
ehci_data.port_mode[i] = pdata->port_mode[i];
ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
ehci_data.regulator[i] = pdata->regulator[i];
+ ehci_data.transceiver_clk[i] = pdata->transceiver_clk[i];
}
ehci_data.phy_reset = pdata->phy_reset;
ohci_data.es2_compatibility = pdata->es2_compatibility;
usbhs_data.ehci_data = &ehci_data;
usbhs_data.ohci_data = &ohci_data;
+ oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
+ if (!oh[0]) {
+ pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
+ return;
+ }
+
+ oh[1] = omap_hwmod_lookup(USBHS_OHCI_HWMODNAME);
+ if (!oh[1]) {
+ pr_err("Could not look up %s\n", USBHS_OHCI_HWMODNAME);
+ return;
+ }
+
+ oh[2] = omap_hwmod_lookup(USBHS_EHCI_HWMODNAME);
+ if (!oh[2]) {
+ pr_err("Could not look up %s\n", USBHS_EHCI_HWMODNAME);
+ return;
+ }
+
+ oh[3] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
+ if (!oh[3]) {
+ pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
+ return;
+ }
+
if (cpu_is_omap34xx()) {
- usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE;
- usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
- usbhs_resources[1].start = OMAP34XX_USBTLL_BASE;
- usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1;
- usbhs_resources[2].start = OMAP34XX_EHCI_BASE;
- usbhs_resources[2].end = OMAP34XX_EHCI_BASE + SZ_1K - 1;
- usbhs_resources[3].start = INT_34XX_EHCI_IRQ;
- usbhs_resources[4].start = OMAP34XX_OHCI_BASE;
- usbhs_resources[4].end = OMAP34XX_OHCI_BASE + SZ_1K - 1;
- usbhs_resources[5].start = INT_34XX_OHCI_IRQ;
setup_ehci_io_mux(pdata->port_mode);
setup_ohci_io_mux(pdata->port_mode);
} else if (cpu_is_omap44xx()) {
- usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE;
- usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1;
- usbhs_resources[1].start = OMAP44XX_USBTLL_BASE;
- usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1;
- usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE;
- usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
- usbhs_resources[3].start = OMAP44XX_IRQ_EHCI;
- usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE;
- usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1;
- usbhs_resources[5].start = OMAP44XX_IRQ_OHCI;
- setup_4430ehci_io_mux(pdata->port_mode);
- setup_4430ohci_io_mux(pdata->port_mode);
+ oh[2]->mux = setup_4430ehci_io_mux(pdata->port_mode);
+ oh[1]->mux = setup_4430ohci_io_mux(pdata->port_mode);
}
- if (platform_device_add_data(&usbhs_device,
- &usbhs_data, sizeof(usbhs_data)) < 0) {
- printk(KERN_ERR "USBHS platform_device_add_data failed\n");
- goto init_end;
+ od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 4,
+ (void *)&usbhs_data, sizeof(usbhs_data),
+ omap_uhhtll_latency,
+ ARRAY_SIZE(omap_uhhtll_latency), false);
+
+ if (IS_ERR(od)) {
+ pr_err("Could not build hwmod devices %s, %s\n",
+ USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME);
+ return;
}
- if (platform_device_register(&usbhs_device) < 0)
- printk(KERN_ERR "USBHS platform_device_register failed\n");
+ usbhs_wake = kmalloc(sizeof(*usbhs_wake), GFP_KERNEL);
+ if (!usbhs_wake) {
+ pr_err("Could not allocate usbhs_wake\n");
+ return;
+ }
-init_end:
- return;
+ INIT_WORK(&usbhs_wake->wakeup_work, usbhs_resume_work);
+ usbhs_wake->oh_ehci = oh[2];
+ usbhs_wake->oh_ohci = oh[1];
+ usbhs_wake->dev = &od->pdev.dev;
}
#else
+void usbhs_wakeup()
+{
+}
+
void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
{
}
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index c7ed540..bd3b513 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -119,7 +119,7 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
struct omap_hwmod *oh;
struct omap_device *od;
struct platform_device *pdev;
- struct device *dev;
+ struct device *dev = NULL;
int bus_id = -1;
const char *oh_name, *name;
struct omap_musb_board_data *board_data;
@@ -140,7 +140,7 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
musb_plat.extvbus = board_data->extvbus;
if (cpu_is_omap44xx())
- omap4430_phy_init(dev);
+ omap4430_phy_init(dev); /* power down the phy */
if (cpu_is_omap3517() || cpu_is_omap3505()) {
oh_name = "am35x_otg_hs";
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
new file mode 100644
index 0000000..42ffc64
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.c
@@ -0,0 +1,636 @@
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <plat/cpu.h>
+
+#include "voltage.h"
+#include "vc.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+#define OMAP_VC_I2C_ACK_DELAY 3
+
+/**
+ * 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,
+ struct omap_volt_data *target_v,
+ 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_v);
+
+ return 0;
+}
+
+/**
+ * omap_vc_set_auto_trans() - set auto transition parameters for a domain
+ * @voltdm: voltage domain we are interested in
+ * @flag: which state should we program this to
+ */
+int omap_vc_set_auto_trans(struct voltagedomain *voltdm, u8 flag)
+{
+ struct omap_vc_channel *vc;
+ const struct omap_vc_auto_trans *auto_trans;
+ u8 val = OMAP_VC_CHANNEL_AUTO_TRANSITION_UNSUPPORTED;
+
+ if (!voltdm) {
+ pr_err("%s: NULL Voltage domain!\n", __func__);
+ return -ENOENT;
+ }
+ vc = voltdm->vc;
+ if (!vc) {
+ pr_err("%s: NULL VC Voltage domain %s!\n", __func__,
+ voltdm->name);
+ return -ENOENT;
+ }
+
+ auto_trans = vc->auto_trans;
+ if (!auto_trans) {
+ pr_debug("%s: No auto trans %s!\n", __func__, voltdm->name);
+ return 0;
+ }
+
+ /* Handle value and masks per silicon data */
+ switch (flag) {
+ case OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE:
+ val = 0x0;
+ break;
+ case OMAP_VC_CHANNEL_AUTO_TRANSITION_SLEEP:
+ val = auto_trans->sleep_val;
+ break;
+ case OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION:
+ val = auto_trans->retention_val;
+ break;
+ case OMAP_VC_CHANNEL_AUTO_TRANSITION_OFF:
+ val = auto_trans->off_val;
+ break;
+ default:
+ pr_err("%s: Voltdm %s invalid flag %d\n", __func__,
+ voltdm->name, flag);
+ return -EINVAL;
+ }
+
+ if (val == OMAP_VC_CHANNEL_AUTO_TRANSITION_UNSUPPORTED) {
+ pr_err("%s: transition to %d on %s is NOT supported\n",
+ __func__, flag, voltdm->name);
+ return -EINVAL;
+ }
+
+ /* All ready - set it and move on.. */
+ voltdm->rmw(vc->auto_trans_mask, val << __ffs(vc->auto_trans_mask),
+ auto_trans->reg);
+ return 0;
+}
+
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ struct omap_volt_data *target_vdata,
+ u8 target_vsel, u8 current_vsel)
+{
+ struct omap_vc_channel *vc;
+ u32 smps_steps = 0, smps_delay = 0;
+ u8 on_vsel, onlp_vsel;
+ u32 val;
+
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_err("%s bad voldm\n", __func__);
+ return;
+ }
+
+ vc = voltdm->vc;
+ if (IS_ERR_OR_NULL(vc)) {
+ pr_err("%s voldm=%s bad vc\n", __func__, voltdm->name);
+ return;
+ }
+
+ 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_vdata;
+
+ /* Set up the on voltage for wakeup from lp and OFF */
+ on_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+ onlp_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+ val = (on_vsel << vc->common->cmd_on_shift) |
+ (onlp_vsel << vc->common->cmd_onlp_shift) |
+ vc->setup_voltage_common;
+ voltdm->write(val, vc->cmdval_reg);
+}
+
+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,
+ struct omap_volt_data *target_v)
+{
+ struct omap_vc_channel *vc;
+ u8 target_vsel, current_vsel;
+ int ret;
+ unsigned long target_volt = omap_get_operation_voltage(target_v);
+
+ 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_v, &target_vsel,
+ &current_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_v, 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;
+}
+
+/**
+ * omap_vc_setup_lp_time() - configure the voltage ramp time for low states.
+ * @voltdm: voltagedomain we are interested in.
+ * @is_retention: Are we interested in retention or OFF?
+ *
+ * The ramp times are calculated based on the worst case voltage drop,
+ * which is the difference of on_volt and the ret_volt. This time is used
+ * for computing the duration necessary for low power states such as retention.
+ */
+static int __init omap_vc_setup_lp_time(struct voltagedomain *voltdm,
+ bool is_retention)
+{
+ u32 volt_drop = 0, volt_ramptime = 0, volt_rampcount;
+ u32 sys_clk_mhz = 0, sysclk_cycles = 0, max_latency_for_prescaler = 0;
+ struct clk *sys_ck;
+ u8 pre_scaler = 0;
+ struct omap_voltdm_pmic *pmic = voltdm->pmic;
+ struct omap_vc_channel *vc = voltdm->vc;
+ const struct setup_time_ramp_params *params;
+
+ params = vc->common->setup_time_params;
+ /* If the VC data does not have params for us, return PMIC's value */
+ if (!params)
+ return pmic->volt_setup_time;
+ if (!params->pre_scaler_to_sysclk_cycles_count)
+ return pmic->volt_setup_time;
+
+ /* No of sys_clk cycles for pre_scaler 0 */
+ sysclk_cycles = params->pre_scaler_to_sysclk_cycles[0];
+
+ sys_ck = clk_get(NULL, "sys_clkin_ck");
+ if (IS_ERR_OR_NULL(sys_ck)) {
+ WARN_ONCE(1, "%s: unable to get sys_clkin_ck (voldm %s)\n",
+ __func__, voltdm->name);
+ return pmic->volt_setup_time;
+ }
+ sys_clk_mhz = clk_get_rate(sys_ck) / 1000000;
+ clk_put(sys_ck);
+
+ /*
+ * If we chose prescaler 0x0, then we have a limit on the maximum
+ * latency for which we can chose a correct count. This is because,
+ * the count field is limited to 6 bits and max value can be 63 and
+ * for prescaler 0, ramp up/down counter is incremented every
+ * 64 system clock cycles.
+ * for eg, max latency for prescaler for 38.4Mhz sys clk would be
+ * 105 = (63 * 64) / 38.4
+ */
+ max_latency_for_prescaler = (63 * sysclk_cycles) / sys_clk_mhz;
+
+ if (is_retention)
+ volt_drop = pmic->on_volt - pmic->ret_volt;
+ else
+ volt_drop = pmic->on_volt;
+ volt_ramptime = DIV_ROUND_UP(volt_drop, pmic->slew_rate);
+ volt_ramptime += OMAP_VC_I2C_ACK_DELAY;
+
+ /* many PMICs need additional time to switch back on */
+ if (!is_retention)
+ volt_ramptime += pmic->switch_on_time;
+
+ if (volt_ramptime < max_latency_for_prescaler)
+ pre_scaler = 0x0;
+ else
+ pre_scaler = 0x1;
+
+ /*
+ * IF we mess up values, then try to have some form of recovery using
+ * PMIC's value.
+ */
+ if (pre_scaler > params->pre_scaler_to_sysclk_cycles_count) {
+ pr_err("%s: prescaler idx %d > available %d on domain %s\n",
+ __func__, pre_scaler,
+ params->pre_scaler_to_sysclk_cycles_count, voltdm->name);
+ return pmic->volt_setup_time;
+ }
+
+ sysclk_cycles = params->pre_scaler_to_sysclk_cycles[pre_scaler];
+
+ volt_rampcount = ((volt_ramptime * sys_clk_mhz) / sysclk_cycles) + 1;
+
+ return (pre_scaler << OMAP4430_RAMP_DOWN_PRESCAL_SHIFT) |
+ (pre_scaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) |
+ (volt_rampcount << OMAP4430_RAMP_DOWN_COUNT_SHIFT) |
+ (volt_rampcount << OMAP4430_RAMP_UP_COUNT_SHIFT);
+}
+
+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;
+ /* Calculate the RET voltage setup time and update volt_setup_time */
+ vc->setup_time = omap_vc_setup_lp_time(voltdm, true);
+
+ 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);
+ vc->setup_voltage_common =
+ (ret_vsel << vc->common->cmd_ret_shift) |
+ (off_vsel << vc->common->cmd_off_shift);
+ val = (on_vsel << vc->common->cmd_on_shift) |
+ (onlp_vsel << vc->common->cmd_onlp_shift) |
+ vc->setup_voltage_common;
+ 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);
+ voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+ omap_vc_setup_lp_time(voltdm, false) <<
+ ffs(voltdm->vfsm->voltsetup_mask),
+ voltdm->vfsm->voltsetupoff_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..66c6d9a 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -19,8 +19,26 @@
#include <linux/kernel.h>
+struct voltagedomain;
+
+/**
+ * struct setup_time_ramp_params - ramp time parameters
+ * @pre_scaler_to_sysclk_cycles: The array represents correlation of prescaler
+ * to the number of system clock cycles, for which rampdown counter is
+ * incremented or decremented in PRM_VOLTSETUP_XXX_RET_SLEEP registers.
+ * This is to handle variances in defined values due to conditions such
+ * as "Errata Id: i623: Retention/Sleep Voltage Transitions Ramp Time"
+ * @pre_scaler_to_sysclk_cycles_count: number of entries available
+ *
+ * Add parameters that allow us to compute the ramp time for the device
+ */
+struct setup_time_ramp_params {
+ u16 *pre_scaler_to_sysclk_cycles;
+ u8 pre_scaler_to_sysclk_cycles_count;
+};
+
/**
- * 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 +51,20 @@
* @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
+ * @setup_time_params: setup time parameters
*
* 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 +73,92 @@ 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;
+ struct setup_time_ramp_params *setup_time_params;
+};
+
+/**
+ * struct omap_vc_auto_trans - describe the auto transition for the domain
+ * @reg: register to modify (usually PRM_VOLTCTRL)
+ * @sleep_val: value to set for enabling sleep transition
+ * @retention_val: value to set for enabling retention transition
+ * @off_val: value to set for enabling off transition
+ */
+struct omap_vc_auto_trans {
+ u8 reg;
+ u8 sleep_val;
+ u8 retention_val;
+ u8 off_val;
};
+/* 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
+ * @auto_trans: Auto transition information
+ * @auto_trans_mask: Auto transition mask for this channel
*/
-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;
+ u32 setup_time;
+ u32 setup_voltage_common;
+ 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;
+
+ const struct omap_vc_auto_trans *auto_trans;
+ u32 auto_trans_mask;
};
-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_channel omap4_vc_mpu;
+extern struct omap_vc_channel omap4_vc_iva;
+extern struct omap_vc_channel omap4_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;
+void omap_vc_init_channel(struct voltagedomain *voltdm);
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ struct omap_volt_data *target_vdata,
+ u8 *target_vsel, u8 *current_vsel);
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ struct omap_volt_data *target_vdata,
+ u8 target_vsel, u8 current_vsel);
+/* Auto transition flags for users */
+#define OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE 0
+#define OMAP_VC_CHANNEL_AUTO_TRANSITION_SLEEP 1
+#define OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION 2
+#define OMAP_VC_CHANNEL_AUTO_TRANSITION_OFF 3
+/* For silicon data to mark unsupported transition */
+#define OMAP_VC_CHANNEL_AUTO_TRANSITION_UNSUPPORTED 0xff
+int omap_vc_set_auto_trans(struct voltagedomain *voltdm, u8 flag);
+int omap_vc_bypass_scale_voltage(struct voltagedomain *voltdm,
+ struct omap_volt_data *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..c21d3f5 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,42 @@ 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,
+/*
+ * VC auto transition settings for OMAP3. On OMAP3, we just have a single
+ * device wide state that is achieved on core, so we shall use this data
+ * only for core domain transition
+ */
+static const struct omap_vc_auto_trans omap3_vc_auto_trans = {
+ .reg = OMAP3_PRM_VOLTCTRL_OFFSET,
+ .sleep_val = OMAP3430_AUTO_SLEEP_MASK,
+ .retention_val = OMAP3430_AUTO_RET_MASK,
+ .off_val = OMAP3430_AUTO_OFF_MASK,
+};
+
+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,
+
+ .auto_trans = &omap3_vc_auto_trans,
+ .auto_trans_mask = OMAP3430_AUTO_OFF_MASK | OMAP3430_AUTO_RET_MASK |
+ OMAP3430_AUTO_SLEEP_MASK,
};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
index a98da8d..08f845b 100644
--- a/arch/arm/mach-omap2/vc44xx_data.c
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -26,13 +26,20 @@
#include "vc.h"
+static u16 pre_scaler_to_sysclk_cycles_44xx[] = {16, 64, 128, 512};
+static struct setup_time_ramp_params omap4_vc_setuptime_params = {
+ .pre_scaler_to_sysclk_cycles = pre_scaler_to_sysclk_cycles_44xx,
+ .pre_scaler_to_sysclk_cycles_count = 4,
+};
+
/*
* 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 +50,56 @@ 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,
+ .setup_time_params = &omap4_vc_setuptime_params,
+};
+
+/* VC auto transition settings for OMAP4. */
+static const struct omap_vc_auto_trans omap4_vc_auto_trans = {
+ .reg = OMAP4_PRM_VOLTCTRL_OFFSET,
+ .sleep_val = OMAP4430_AUTO_CTRL_VDD_SLEEP_MASK,
+ .retention_val = OMAP4430_AUTO_CTRL_VDD_RET_MASK,
+ .off_val = OMAP_VC_CHANNEL_AUTO_TRANSITION_UNSUPPORTED,
};
/* 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,
+
+ .auto_trans = &omap4_vc_auto_trans,
+ .auto_trans_mask = OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK,
};
-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,
+
+ .auto_trans = &omap4_vc_auto_trans,
+ .auto_trans_mask = OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK,
};
-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,
+
+ .auto_trans = &omap4_vc_auto_trans,
+ .auto_trans_mask = OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK,
};
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 9ef3789..995c38f 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)
+static int __init _config_common_vdd_data(struct voltagedomain *voltdm)
{
- return omap2_prm_read_mod_reg(mod, offset);
-}
-
-static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
- 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;
- }
-
- 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);
- }
+ voltdm->scale = omap_vp_forceupdate_scale;
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, &current_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, &current_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;
@@ -670,205 +88,95 @@ ovdc_out:
/* Public functions */
/**
- * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
+ * omap_voltage_get_curr_vdata() - Gets the current voltage data
* @voltdm: pointer to the VDD for which current voltage info is needed
*
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
- */
-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;
-}
-
-/**
- * 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.
+ * API to get the current voltage data pointer for a VDD, returns NULL on error
*/
-void omap_vp_disable(struct voltagedomain *voltdm)
+struct omap_volt_data *omap_voltage_get_curr_vdata(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;
+ return NULL;
}
- /* 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;
+ return voltdm->curr_volt;
}
/**
- * 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,
+ struct omap_volt_data *target_v)
{
- struct omap_vdd_info *vdd;
+ int ret = 0;
+ struct omap_voltage_notifier notify;
+ unsigned long target_volt = omap_get_operation_voltage(target_v);
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);
+ notify.voltdm = voltdm;
+ notify.target_volt = target_volt;
+
+ srcu_notifier_call_chain(&voltdm->change_notify_list,
+ OMAP_VOLTAGE_PRECHANGE,
+ (void *)&notify);
+
+ ret = voltdm->scale(voltdm, target_v);
+ if (ret)
+ pr_err("%s: voltage scale failed for vdd%s: %d\n",
+ __func__, voltdm->name, ret);
+
+ notify.op_result = ret;
+ srcu_notifier_call_chain(&voltdm->change_notify_list,
+ OMAP_VOLTAGE_POSTCHANGE,
+ (void *)&notify);
+
+ return ret;
}
/**
- * 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.
+ *
+ * NOTE: appropriate locks should be held for mutual exclusivity.
*/
-void omap_voltage_reset(struct voltagedomain *voltdm)
+void voltdm_reset(struct voltagedomain *voltdm)
{
- unsigned long target_uvdc;
+ struct omap_volt_data *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_curr_vdata(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 +201,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 +232,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",
@@ -937,8 +245,8 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
return &vdd->volt_data[i];
}
- pr_notice("%s: Unable to match the current voltage with the voltage"
- "table for vdd_%s\n", __func__, voltdm->name);
+ pr_notice("%s: Unable to match the current voltage %lu with the voltage"
+ "table for vdd_%s\n", __func__, volt, voltdm->name);
return ERR_PTR(-ENODATA);
}
@@ -947,54 +255,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 +284,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 +304,147 @@ 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 dyn_volt_debug_get(void *data, u64 *val)
+{
+ struct voltagedomain *voltdm = (struct voltagedomain *)data;
+ struct omap_volt_data *volt_data;
+
+ if (!voltdm) {
+ pr_warning("%s: Wrong paramater passed\n", __func__);
+ return -EINVAL;
}
+ volt_data = omap_voltage_get_curr_vdata(voltdm);
+ if (IS_ERR_OR_NULL(volt_data)) {
+ pr_warning("%s: No voltage/domain?\n", __func__);
+ return -ENODEV;
+ }
+
+ *val = volt_data->volt_dynamic_nominal;
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(dyn_volt_debug_fops, dyn_volt_debug_get, NULL,
+ "%llu\n");
+
+static int calib_volt_debug_get(void *data, u64 *val)
+{
+ struct voltagedomain *voltdm = (struct voltagedomain *)data;
+ struct omap_volt_data *volt_data;
+
+ if (!voltdm) {
+ pr_warning("%s: Wrong paramater passed\n", __func__);
+ return -EINVAL;
+ }
+
+ volt_data = omap_voltage_get_curr_vdata(voltdm);
+ if (IS_ERR_OR_NULL(volt_data)) {
+ pr_warning("%s: No voltage/domain?\n", __func__);
+ return -ENODEV;
+ }
+
+ *val = volt_data->volt_calibrated;
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(calib_volt_debug_fops, calib_volt_debug_get, NULL,
+ "%llu\n");
+static int margin_volt_debug_get(void *data, u64 *val)
+{
+ struct voltagedomain *voltdm = (struct voltagedomain *) data;
+ struct omap_volt_data *vdata;
+
+ if (!voltdm) {
+ pr_warning("%s: Wrong parameter passed\n", __func__);
+ return -EINVAL;
+ }
+
+ vdata = omap_voltage_get_curr_vdata(voltdm);
+ if (IS_ERR_OR_NULL(vdata)) {
+ pr_warning("%s: unable to get volt for vdd_%s\n",
+ __func__, voltdm->name);
+ return -ENODEV;
+ }
+ *val = vdata->volt_margin;
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(margin_volt_debug_fops, margin_volt_debug_get, NULL,
+ "%llu\n");
+
+static int nom_volt_debug_get(void *data, u64 *val)
+{
+ struct voltagedomain *voltdm = (struct voltagedomain *) data;
+ struct omap_volt_data *vdata;
+
+ if (!voltdm) {
+ pr_warning("Wrong paramater passed\n");
+ return -EINVAL;
+ }
+
+ vdata = omap_voltage_get_curr_vdata(voltdm);
+ if (IS_ERR_OR_NULL(vdata)) {
+ pr_warning("%s: unable to get volt for vdd_%s\n",
+ __func__, voltdm->name);
+ return -ENODEV;
+ }
+ *val = vdata->volt_nominal;
+
+ 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);
+ (void) debugfs_create_file("curr_dyn_nominal_volt", S_IRUGO,
+ voltdm->debug_dir, (void *) voltdm,
+ &dyn_volt_debug_fops);
+ (void) debugfs_create_file("curr_calibrated_volt", S_IRUGO,
+ voltdm->debug_dir, (void *) voltdm,
+ &calib_volt_debug_fops);
+ (void) debugfs_create_file("curr_margin_volt", S_IRUGO,
+ voltdm->debug_dir, (void *) voltdm,
+ &margin_volt_debug_fops);
}
/**
@@ -1070,37 +456,212 @@ 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 (voltdm->abb)
+ omap_ldo_abb_init(voltdm);
+
+ if (voltage_dir)
+ voltdm_debugfs_init(voltage_dir, voltdm);
+
+ srcu_init_notifier_head(&voltdm->change_notify_list);
}
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;
+}
+
+/**
+ * omap_voltage_calib_reset() - reset the calibrated voltage entries
+ * @voltdm: voltage domain to reset the entries for
+ *
+ * when the calibrated entries are no longer valid, this api allows
+ * the calibrated voltages to be reset.
+ *
+ * NOTE: Appropriate locks must be held by calling path to ensure mutual
+ * exclusivity
+ */
+int omap_voltage_calib_reset(struct voltagedomain *voltdm)
+{
+ struct omap_volt_data *volt_data;
+
+ if (!voltdm) {
+ pr_warning("%s: voltdm NULL!\n", __func__);
+ return -EINVAL;
+ }
+
+ volt_data = voltdm->vdd->volt_data;
+
+ /* reset the calibrated voltages as 0 */
+ while (volt_data->volt_nominal) {
+ volt_data->volt_calibrated = 0;
+ volt_data++;
+ }
return 0;
}
+
+/**
+ * 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..c454129 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -14,10 +14,16 @@
#ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+#include <linux/notifier.h>
#include <linux/err.h>
+struct omap_volt_data;
+
#include "vc.h"
#include "vp.h"
+#include "ldo.h"
+
+struct powerdomain;
/* XXX document */
#define VOLTSCALE_VPFORCEUPDATE 1
@@ -31,35 +37,105 @@
#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
+ * @voltsetup_mask: SETUP_TIME* bitmask of PRM_VOLTSETUP* register(RET/SLEEP)
+ * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base(RET/SLEEP)
* @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
+ * @voltsetupoff_reg: register offset of PRM_VOLTSETUP*_OFF from PRM base
*
* XXX What about VOLTOFFSET/VOLTCTRL?
* 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;
+ u8 voltsetupoff_reg;
};
+/* Dynamic nominal voltage margin common for OMAP3630 and OMAP4 */
+#define OMAP3PLUS_DYNAMIC_NOMINAL_MARGIN_UV 50000
+
/**
* 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
+ * @change_notify_list: notifiers that need to be told on pre and post change
*/
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;
+ struct omap_ldo_abb_instance *abb;
+
+ /* 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,
+ struct omap_volt_data *target_volt);
+ struct omap_volt_data *curr_volt;
+
+ struct omap_vdd_info *vdd;
+ struct srcu_notifier_head change_notify_list;
+ struct dentry *debug_dir;
+};
+
+/* Notifier values for voltage changes */
+#define OMAP_VOLTAGE_PRECHANGE 1
+#define OMAP_VOLTAGE_POSTCHANGE 2
+
+/**
+ * struct omap_voltage_notifier - notifier data that is passed along
+ * @voltdm: voltage domain for the notification
+ * @target_volt: what voltage is happening
+ * @op_result: valid only for POSTCHANGE, tells the result of
+ * the operation.
+ *
+ * This provides notification
+ */
+struct omap_voltage_notifier {
+ struct voltagedomain *voltdm;
+ unsigned long target_volt;
+ int op_result;
};
+/* Flags for various ABB options */
+#define OMAP_ABB_NONE -1
+#define OMAP_ABB_NOMINAL_OPP 0
+#define OMAP_ABB_FAST_OPP 1
+
/**
* struct omap_volt_data - Omap voltage specific data.
* @voltage_nominal: The possible voltage value in uV
+ * @voltage_calibrated: The Calibrated voltage value in uV
+ * @voltage_dynamic_nominal: The run time optimized nominal voltage for
+ * the device. Dynamic nominal is the nominal voltage
+ * specialized for that OPP on the device in uV.
+ * @volt_margin: Additional sofware margin in uV to add to OPP calibrated
+ * voltage
* @sr_efuse_offs: The offset of the efuse register(from system
* control module base address) from where to read
* the n-target value for the smartreflex module.
@@ -68,22 +144,69 @@ struct voltagedomain {
* with voltage.
* @vp_errorgain: Error gain value for the voltage processor. This
* field also differs according to the voltage/opp.
+ * @abb_type: Either OMAP_ABB_NONE - which implies that there is no
+ * usage of ABB; OMAP_ABB_NOMINAL_OPP - which bypasses ABB
+ * LDO; or OMAP_ABB_FAST_OPP, which enables Forward-Body
+ * Bias.
*/
struct omap_volt_data {
u32 volt_nominal;
+ u32 volt_calibrated;
+ u32 volt_dynamic_nominal;
+ u32 volt_margin;
u32 sr_efuse_offs;
u8 sr_errminlimit;
u8 vp_errgain;
+ int abb_type;
};
+/*
+ * 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)
+ * @switch_on_time: time taken for switch on the DCDC in uSec
*/
-struct omap_volt_pmic_info {
+struct omap_voltdm_pmic {
int slew_rate;
int step_size;
u32 on_volt;
@@ -91,81 +214,83 @@ struct omap_volt_pmic_info {
u32 ret_volt;
u32 off_volt;
u16 volt_setup_time;
+ u16 switch_on_time;
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
+ * @volt_data : Array ending with a 0 terminator containing the
+ * voltage table with 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);
+struct omap_volt_data *omap_voltage_get_curr_vdata(struct voltagedomain *voldm);
#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 +300,69 @@ static inline int omap_voltage_late_init(void)
{
return -EINVAL;
}
-static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
+#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,
+ struct omap_volt_data *target_volt);
+void voltdm_reset(struct voltagedomain *voltdm);
+
+static inline int voltdm_register_notifier(struct voltagedomain *voltdm,
+ struct notifier_block *nb)
+{
+ return srcu_notifier_chain_register(&voltdm->change_notify_list, nb);
+}
+
+static inline int voltdm_unregister_notifier(struct voltagedomain *voltdm,
+ struct notifier_block *nb)
{
- return ERR_PTR(-EINVAL);
+ return srcu_notifier_chain_unregister(&voltdm->change_notify_list, nb);
}
-#endif
+
+/* convert volt data to the voltage for the voltage data */
+static inline unsigned long omap_get_operation_voltage(
+ struct omap_volt_data *vdata)
+{
+ if (!vdata)
+ return 0;
+ return (vdata->volt_calibrated) ? vdata->volt_calibrated :
+ (vdata->volt_dynamic_nominal) ? vdata->volt_dynamic_nominal :
+ vdata->volt_nominal;
+}
+
+/* what is my dynamic nominal? */
+static inline unsigned long omap_get_dyn_nominal(struct omap_volt_data *vdata)
+{
+ if (IS_ERR_OR_NULL(vdata))
+ return 0;
+ if (vdata->volt_calibrated) {
+ unsigned long v = vdata->volt_calibrated +
+ OMAP3PLUS_DYNAMIC_NOMINAL_MARGIN_UV;
+ if (v > vdata->volt_nominal)
+ return vdata->volt_nominal;
+ return v;
+ }
+ return vdata->volt_nominal;
+}
+static inline unsigned long omap_get_nominal_voltage(
+ struct omap_volt_data *vdata)
+{
+ if (IS_ERR_OR_NULL(vdata))
+ return 0;
+ return vdata->volt_nominal;
+}
+
+int omap_voltage_calib_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..65a00ff 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -26,55 +26,69 @@
#include "voltage.h"
#include "vc.h"
#include "vp.h"
+#include "ldo.h"
/*
* 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 +97,17 @@ 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;
+ omap3_voltdm_mpu.abb = &omap3630_ldo_abb_mpu_instance;
+
} 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..dc5026e 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>
@@ -31,72 +32,135 @@
#include "omap_opp_data.h"
#include "vc.h"
#include "vp.h"
+#include "ldo.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,
+ .voltsetup_mask = OMAP4430_RAMP_DOWN_PRESCAL_MASK |
+ OMAP4430_RAMP_DOWN_COUNT_MASK |
+ OMAP4430_RAMP_UP_PRESCAL_MASK |
+ OMAP4430_RAMP_UP_COUNT_MASK,
+ .voltsetupoff_reg = OMAP4_PRM_VOLTSETUP_MPU_OFF_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,
+ .voltsetup_mask = OMAP4430_RAMP_DOWN_PRESCAL_MASK |
+ OMAP4430_RAMP_DOWN_COUNT_MASK |
+ OMAP4430_RAMP_UP_PRESCAL_MASK |
+ OMAP4430_RAMP_UP_COUNT_MASK,
+ .voltsetupoff_reg = OMAP4_PRM_VOLTSETUP_IVA_OFF_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,
+ .voltsetup_mask = OMAP4430_RAMP_DOWN_PRESCAL_MASK |
+ OMAP4430_RAMP_DOWN_COUNT_MASK |
+ OMAP4430_RAMP_UP_PRESCAL_MASK |
+ OMAP4430_RAMP_UP_COUNT_MASK,
+ .voltsetupoff_reg = OMAP4_PRM_VOLTSETUP_CORE_OFF_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,
+ .abb = &omap4_ldo_abb_mpu_instance,
};
-/* 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_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,
+ .abb = &omap4_ldo_abb_iva_instance,
};
-/* 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_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,
+};
+
+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,
+};
+
+/*
+ * Handle Mutant pre_scalar to sysclk cycles map:
+ * Due to "Errata Id: i623: Retention/Sleep Voltage Transitions Ramp Time"
+ * on OMAP4430 specifically, the maps is 64, 256, 512, 2048 cycles.
+ * Handle this condition dynamically from version detection logic
+ */
+static u16 pre_scaler_to_sysclk_cycles_443x[] = {64, 256, 512, 2048};
- 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()) {
+ struct setup_time_ramp_params *params =
+ omap4_vc_core.common->setup_time_params;
+
+ if (params) {
+ params->pre_scaler_to_sysclk_cycles =
+ pre_scaler_to_sysclk_cycles_443x;
+ }
+ 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..3f16be5
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.c
@@ -0,0 +1,426 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ratelimit.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;
+ struct omap_volt_data *v = omap_voltage_get_curr_vdata(voltdm);
+ u32 vpconfig;
+ unsigned long uvdc;
+ char vsel;
+
+ if (IS_ERR_OR_NULL(v)) {
+ pr_warning("%s: unable to get voltage for vdd_%s\n",
+ __func__, voltdm->name);
+ return;
+ }
+ uvdc = omap_get_operation_voltage(v);
+ 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 = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate,
+ 1000 * voltdm->pmic->slew_rate);
+ 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);
+}
+
+/**
+ * omap_vp_is_transdone() - is voltage transfer done on vp?
+ * @voltdm: pointer to the VDD which is to be scaled.
+ *
+ * VP's transdone bit is the only way to ensure that the transfer
+ * of the voltage value has actually been send over to the PMIC
+ * This is hence useful for all users of voltage domain to precisely
+ * identify once the PMIC voltage has been set by the voltage processor
+ */
+bool omap_vp_is_transdone(struct voltagedomain *voltdm)
+{
+
+ struct omap_vp_instance *vp = voltdm->vp;
+
+ return vp->common->ops->check_txdone(vp->id) ? true : false;
+}
+
+/**
+ * omap_vp_clear_transdone() - clear voltage transfer done status on vp
+ * @voltdm: pointer to the VDD which is to be scaled.
+ */
+void omap_vp_clear_transdone(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+
+ vp->common->ops->clear_txdone(vp->id);
+
+ return;
+}
+
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+ struct omap_volt_data *volt_data)
+{
+ if (IS_ERR_OR_NULL(volt_data)) {
+ pr_err("%s: vdm %s bad voltage data %p\n", __func__,
+ voltdm->name, 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;
+}
+
+#define _MAX_RETRIES_BEFORE_RECOVER 50
+#define _MAX_COUNT_ERR 10
+static u8 __vp_debug_error_message_count = _MAX_COUNT_ERR;
+static u8 __vp_recover_count = _MAX_RETRIES_BEFORE_RECOVER;
+/* Dump with stack the first few messages, tone down severity for the rest */
+#define _vp_controlled_err(vp, voltdm, ARGS...) \
+{ \
+ if (__vp_debug_error_message_count) { \
+ pr_err(ARGS); \
+ dump_stack(); \
+ __vp_debug_error_message_count--; \
+ } else { \
+ pr_err_ratelimited(ARGS); \
+ } \
+ if ((vp)->common->ops->recover && !(--__vp_recover_count)) { \
+ pr_err("%s:domain %s recovery count triggered\n", \
+ __func__, (voltdm)->name); \
+ (vp)->common->ops->recover((vp)->id); \
+ __vp_recover_count =_MAX_RETRIES_BEFORE_RECOVER; \
+ } \
+}
+
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+ struct omap_volt_data *target_v)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 vpconfig;
+ u8 target_vsel, current_vsel;
+ int ret, timeout = 0;
+ unsigned long target_volt = omap_get_operation_voltage(target_v);
+
+ /*
+ * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+ * This is an additional allowance to ensure we are in proper state
+ * to enter into forceupdate state transition.
+ */
+ omap_test_timeout((voltdm->read(vp->vstatus) & vp->common->vstatus_vpidle),
+ VP_IDLE_TIMEOUT, timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ _vp_controlled_err(vp, voltdm,
+ "%s:vdd_%s idletimdout forceupdate(v=%ld)\n",
+ __func__, voltdm->name, target_volt);
+
+ ret = omap_vc_pre_scale(voltdm, target_volt, target_v,
+ &target_vsel, &current_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) {
+ _vp_controlled_err(vp, voltdm,
+ "%s: vdd_%s TRANXDONE timeout exceeded."
+ "Voltage change aborted target volt=%ld,"
+ "target vsel=0x%02x, current_vsel=0x%02x\n",
+ __func__, voltdm->name, target_volt,
+ target_vsel, current_vsel);
+ 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)
+ _vp_controlled_err(vp, voltdm,
+ "%s: vdd_%s TRANXDONE timeout exceeded. "
+ "TRANXDONE never got set after the voltage update. "
+ "target volt=%ld, target vsel=0x%02x, "
+ "current_vsel=0x%02x\n",
+ __func__, voltdm->name, target_volt,
+ target_vsel, current_vsel);
+
+ omap_vc_post_scale(voltdm, target_volt, target_v,
+ 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)
+ _vp_controlled_err(vp, voltdm,
+ "%s: vdd_%s TRANXDONE timeout exceeded while"
+ "trying to clear the TRANXDONE status. target volt=%ld,"
+ "target vsel=0x%02x, current_vsel=0x%02x\n",
+ __func__, voltdm->name, target_volt,
+ target_vsel, current_vsel);
+
+ 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;
+ }
+
+ /*
+ * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+ * Depending on if we catch VP in the middle of an SR operation.
+ */
+ omap_test_timeout((voltdm->read(vp->vstatus) & vp->common->vstatus_vpidle),
+ VP_IDLE_TIMEOUT, timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ pr_warning("%s: vdd_%s idle timedout before disable\n",
+ __func__, voltdm->name);
+
+ /* 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->common->vstatus_vpidle),
+ VP_IDLE_TIMEOUT, timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ pr_warning("%s: vdd_%s idle timedout after disable\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..cb3465a 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -19,44 +19,53 @@
#include <linux/kernel.h>
+struct voltagedomain;
+
/* XXX document */
-#define VP_IDLE_TIMEOUT 200
+#define VP_IDLE_TIMEOUT 500
#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);
+ void (*recover)(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 vstatus_vpidle;
u8 vstepmin_stepmin_shift;
u8 vstepmin_smpswaittimemin_shift;
u8 vstepmax_stepmax_shift;
@@ -64,80 +73,51 @@ 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,
+ struct omap_volt_data *target_v);
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+ struct omap_volt_data *volt_data);
+bool omap_vp_is_transdone(struct voltagedomain *voltdm);
+void omap_vp_clear_transdone(struct voltagedomain *voltdm);
#endif
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
index 6452170..6db2604 100644
--- a/arch/arm/mach-omap2/vp3xxx_data.c
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -25,21 +25,26 @@
#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,
.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK,
.vpconfig_vpenable = OMAP3430_VPENABLE_MASK,
+ .vstatus_vpidle = OMAP3430_VPINIDLE_MASK,
.vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT,
.vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT,
.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT,
@@ -47,36 +52,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_PRM_IRQ_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_PRM_IRQ_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..da6fed9 100644
--- a/arch/arm/mach-omap2/vp44xx_data.c
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -21,26 +21,38 @@
#include <plat/common.h>
+#include "pm.h"
#include "prm44xx.h"
#include "prm-regbits-44xx.h"
#include "voltage.h"
#include "vp.h"
+/* OMAP4 is hooked such that only a cold reset will reset VP */
+static void omap4_vp_recover(u8 vp_id)
+{
+ omap4_pm_cold_reset("Voltage Processor Recovery");
+}
+
+static const struct omap_vp_ops omap4_vp_ops = {
+ .check_txdone = omap4_prm_vp_check_txdone,
+ .clear_txdone = omap4_prm_vp_clear_txdone,
+ .recover = omap4_vp_recover,
+};
+
/*
* 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,
.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK,
.vpconfig_vpenable = OMAP4430_VPENABLE_MASK,
+ .vstatus_vpidle = OMAP4430_VPINIDLE_MASK,
.vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT,
.vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT,
.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT,
@@ -48,53 +60,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_PRM_IRQ_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_PRM_IRQ_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_PRM_IRQ_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/mm/context.c b/arch/arm/mm/context.c
index b0ee9ba..131f381 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -99,8 +99,7 @@ static void reset_context(void *info)
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
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 5663650..f00076c 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -357,6 +357,18 @@ dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_
}
EXPORT_SYMBOL(dma_alloc_writecombine);
+/*
+ * Allocate a strongly ordered region, in much the same way as
+ * dma_alloc_coherent above.
+ */
+void *dma_alloc_stronglyordered(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp)
+{
+ return __dma_alloc(dev, size, handle, gfp,
+ pgprot_stronglyordered(pgprot_kernel));
+}
+EXPORT_SYMBOL(dma_alloc_stronglyordered);
+
static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size)
{
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 19d9369..f23e315 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -273,6 +273,14 @@ static struct mem_type mem_types[] = {
.prot_l1 = PMD_TYPE_TABLE,
.domain = DOMAIN_KERNEL,
},
+ [MT_MEMORY_SO] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_MT_UNCACHED,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
+ PMD_SECT_UNCACHED | PMD_SECT_XN,
+ .domain = DOMAIN_KERNEL,
+ },
};
const struct mem_type *get_mem_type(unsigned int type)
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 49a4c75..ef3763c 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -38,6 +38,29 @@ 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_RPMSG_RECOVERY
+ bool "OMAP RPMSG recovery"
+ default y
+ depends on OMAP_RPMSG
+ help
+ Say Y if you want RPMSG to reset the rpmsg channels after a fatal
+ error in remote proc. That way it will restart all the channels and
+ the remote processor, causing a clean restart.
+
config OMAP_SMARTREFLEX
bool "SmartReflex support"
depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
@@ -69,6 +92,26 @@ config OMAP_SMARTREFLEX_CLASS3
Class 3 implementation of Smartreflex employs continuous hardware
voltage calibration.
+config OMAP_SMARTREFLEX_CLASS1P5
+ bool "Class 1.5 mode of Smartreflex Implementation"
+ depends on OMAP_SMARTREFLEX
+ help
+ Say Y to enable Class 1.5 implementation of Smartreflex.
+
+ Class 1.5 implementation of Smartreflex employs software controlled
+ hardware voltage calibration.
+
+config OMAP_SR_CLASS1P5_RECALIBRATION_DELAY
+ int "Class 1.5 mode recalibration recalibration delay(ms)"
+ depends on OMAP_SMARTREFLEX_CLASS1P5
+ default 86400000
+ help
+ Setup the recalibration delay in milliseconds.
+
+ Use 0 for never doing a recalibration (operates in AVS Class 1 mode).
+ Defaults to recommended recalibration every 24hrs.
+ If you do not understand this, use the default.
+
config OMAP_RESET_CLOCKS
bool "Reset unused clocks during boot"
depends on ARCH_OMAP
@@ -116,7 +159,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 +175,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 +249,29 @@ config OMAP_SERIAL_WAKE
to data on the serial RX line. This allows you to wake the
system from serial console.
+config OMAP_TEMP_SENSOR
+ bool "OMAP Temp Sensor Support"
+ depends on ARCH_OMAP4
+ default n
+ help
+ Say Y here if you want support for the temp sensor on OMAP4460.
+ This provides the temperature of the MPU
+ subsystem. Only one instance of on die temperature
+ sensor is present.
+
+# this carveout should probably become generic and not omap specific
+config OMAP_REMOTEPROC_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 +279,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..476d817 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -16,12 +16,13 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
+obj-$(CONFIG_REMOTE_PROC) += rproc_user.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 +32,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/clock.c b/arch/arm/plat-omap/clock.c
index c9122dd..b327956 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -441,6 +441,8 @@ static int __init clk_disable_unused(void)
return 0;
pr_info("clock: disabling unused clocks to save power\n");
+
+ spin_lock_irqsave(&clockfw_lock, flags);
list_for_each_entry(ck, &clocks, node) {
if (ck->ops == &clkops_null)
continue;
@@ -448,10 +450,9 @@ static int __init clk_disable_unused(void)
if (ck->usecount > 0 || !ck->enable_reg)
continue;
- spin_lock_irqsave(&clockfw_lock, flags);
arch_clock->clk_disable_unused(ck);
- spin_unlock_irqrestore(&clockfw_lock, flags);
}
+ spin_unlock_irqrestore(&clockfw_lock, flags);
return 0;
}
@@ -475,8 +476,43 @@ int __init clk_init(struct clk_functions * custom_clocks)
/*
* debugfs support to trace clock tree hierarchy and attributes
*/
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
static struct dentry *clk_debugfs_root;
+static int clk_dbg_show_summary(struct seq_file *s, void *unused)
+{
+ struct clk *c;
+ struct clk *pa;
+
+ seq_printf(s, "%-30s %-30s %-10s %s\n",
+ "clock-name", "parent-name", "rate", "use-count");
+
+ mutex_lock(&clocks_mutex);
+ list_for_each_entry(c, &clocks, node) {
+ pa = c->parent;
+ seq_printf(s, "%-30s %-30s %-10lu %d\n",
+ c->name, pa ? pa->name : "none", c->rate, c->usecount);
+ }
+
+ mutex_unlock(&clocks_mutex);
+ return 0;
+}
+
+static int clk_dbg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_dbg_show_summary, inode->i_private);
+}
+
+static const struct file_operations debug_clock_fops = {
+ .open = clk_dbg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int clk_debugfs_register_one(struct clk *c)
{
int err;
@@ -551,6 +587,12 @@ static int __init clk_debugfs_init(void)
if (err)
goto err_out;
}
+
+ d = debugfs_create_file("summary", S_IRUGO,
+ d, NULL, &debug_clock_fops);
+ if (!d)
+ return -ENOMEM;
+
return 0;
err_out:
debugfs_remove_recursive(clk_debugfs_root);
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index d9f10a3..0c8c8b5 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -20,7 +20,7 @@
#include <plat/board.h>
#include <plat/vram.h>
#include <plat/dsp.h>
-
+#include <plat/remoteproc.h>
#define NO_LENGTH_CHECK 0xffffffff
@@ -65,4 +65,5 @@ void __init omap_reserve(void)
omapfb_reserve_sdram_memblock();
omap_vram_reserve_sdram_memblock();
omap_dsp_reserve_sdram_memblock();
+ omap_ipu_reserve_sdram_memblock();
}
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index f7fed60..91b2ec0 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -18,6 +18,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sched.h>
+#include <linux/syscore_ops.h>
#include <asm/sched_clock.h>
@@ -120,9 +121,40 @@ static DEFINE_CLOCK_DATA(cd);
#define SC_MULT 4000000000u
#define SC_SHIFT 17
+static u32 sched_clock_cyc_offset;
+static u32 sched_clock_cyc_suspend;
+static bool sched_clock_suspended;
+
+static int sched_clock_suspend(void)
+{
+ sched_clock_suspended = true;
+ sched_clock_cyc_suspend = clocksource_32k.read(&clocksource_32k) -
+ sched_clock_cyc_offset;
+
+ return 0;
+}
+
+static void sched_clock_resume(void)
+{
+ sched_clock_cyc_offset = clocksource_32k.read(&clocksource_32k) -
+ sched_clock_cyc_suspend;
+ sched_clock_suspended = false;
+}
+
+static struct syscore_ops sched_clock_syscore_ops = {
+ .suspend = sched_clock_suspend,
+ .resume = sched_clock_resume,
+};
+
static inline unsigned long long notrace _omap_32k_sched_clock(void)
{
- u32 cyc = clocksource_32k.read(&clocksource_32k);
+ u32 cyc;
+ if (!sched_clock_suspended)
+ cyc = clocksource_32k.read(&clocksource_32k) -
+ sched_clock_cyc_offset;
+ else
+ cyc = sched_clock_cyc_suspend;
+
return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
}
@@ -140,7 +172,8 @@ unsigned long long notrace omap_32k_sched_clock(void)
static void notrace omap_update_sched_clock(void)
{
- u32 cyc = clocksource_32k.read(&clocksource_32k);
+ u32 cyc = clocksource_32k.read(&clocksource_32k) -
+ sched_clock_cyc_offset;
update_sched_clock(&cd, cyc, (u32)~0);
}
@@ -152,22 +185,27 @@ static void notrace omap_update_sched_clock(void)
* nsecs and adds to a monotonically increasing timespec.
*/
static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
+static cycles_t cycles;
+static DEFINE_SPINLOCK(read_persistent_clock_lock);
void read_persistent_clock(struct timespec *ts)
{
unsigned long long nsecs;
- cycles_t delta;
- struct timespec *tsp = &persistent_ts;
+ cycles_t last_cycles;
+ unsigned long flags;
+
+ spin_lock_irqsave(&read_persistent_clock_lock, flags);
last_cycles = cycles;
cycles = clocksource_32k.read(&clocksource_32k);
- delta = cycles - last_cycles;
- nsecs = clocksource_cyc2ns(delta,
+ nsecs = clocksource_cyc2ns(cycles - last_cycles,
clocksource_32k.mult, clocksource_32k.shift);
- timespec_add_ns(tsp, nsecs);
- *ts = *tsp;
+ timespec_add_ns(&persistent_ts, nsecs);
+
+ *ts = persistent_ts;
+
+ spin_unlock_irqrestore(&read_persistent_clock_lock, flags);
}
int __init omap_init_clocksource_32k(void)
@@ -202,6 +240,8 @@ int __init omap_init_clocksource_32k(void)
init_fixed_sched_clock(&cd, omap_update_sched_clock, 32,
32768, SC_MULT, SC_SHIFT);
+
+ register_syscore_ops(&sched_clock_syscore_ops);
}
return 0;
}
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index ea28f98..d8add7e7 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -16,17 +16,21 @@
#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/remoteproc.h>
#include <plat/omap44xx.h>
/*-------------------------------------------------------------------------*/
@@ -74,41 +78,6 @@ 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,
- },
- {
- .name = "mcpdm_irq",
- .start = OMAP44XX_IRQ_MCPDM,
- .end = OMAP44XX_IRQ_MCPDM,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-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);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
@@ -190,8 +159,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
@@ -237,6 +204,7 @@ static inline void omap_init_uwire(void) {}
#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE)
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)
{
@@ -256,6 +224,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 +232,73 @@ 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
+
+#if defined(CONFIG_OMAP_REMOTE_PROC)
+static phys_addr_t omap_ipu_phys_mempool_base;
+static u32 omap_ipu_phys_mempool_size;
+static phys_addr_t omap_ipu_phys_st_mempool_base;
+static u32 omap_ipu_phys_st_mempool_size;
+
+void __init omap_ipu_reserve_sdram_memblock(void)
+{
+ /* currently handles only ipu. dsp will be handled later...*/
+ u32 size = CONFIG_OMAP_REMOTEPROC_MEMPOOL_SIZE;
+ phys_addr_t paddr;
+
+ if (!size)
+ return;
+
+ paddr = memblock_alloc(size, SZ_1M);
+ if (!paddr) {
+ pr_err("%s: failed to reserve %x bytes\n",
+ __func__, size);
+ return;
+ }
+ memblock_free(paddr, size);
+ memblock_remove(paddr, size);
+
+ omap_ipu_phys_mempool_base = paddr;
+ omap_ipu_phys_mempool_size = size;
+}
+
+void __init omap_ipu_set_static_mempool(u32 start, u32 size)
+{
+ omap_ipu_phys_st_mempool_base = start;
+ omap_ipu_phys_st_mempool_size = size;
+}
+
+phys_addr_t omap_ipu_get_mempool_base(enum omap_rproc_mempool_type type)
+{
+ switch (type) {
+ case OMAP_RPROC_MEMPOOL_STATIC:
+ return omap_ipu_phys_st_mempool_base;
+ case OMAP_RPROC_MEMPOOL_DYNAMIC:
+ return omap_ipu_phys_mempool_base;
+ default:
+ return 0;
+ }
+}
+EXPORT_SYMBOL(omap_ipu_get_mempool_base);
+
+u32 omap_ipu_get_mempool_size(enum omap_rproc_mempool_type type)
+{
+ switch (type) {
+ case OMAP_RPROC_MEMPOOL_STATIC:
+ return omap_ipu_phys_st_mempool_size;
+ case OMAP_RPROC_MEMPOOL_DYNAMIC:
+ return omap_ipu_phys_mempool_size;
+ default:
+ return 0;
+ }
+}
+EXPORT_SYMBOL(omap_ipu_get_mempool_size);
#endif
/*
@@ -291,7 +327,6 @@ static int __init omap_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_rng();
- omap_init_mcpdm();
omap_init_uwire();
return 0;
}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c22217c..3ec7ec5 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1024,12 +1024,26 @@ EXPORT_SYMBOL(omap_set_dma_callback);
*/
dma_addr_t omap_get_dma_src_pos(int lch)
{
+ u32 cdac;
dma_addr_t offset = 0;
if (cpu_is_omap15xx())
offset = p->dma_read(CPC, lch);
- else
- offset = p->dma_read(CSAC, lch);
+ else {
+ /*
+ * CDAC != 0 indicates that the DMA transfer on the channel has
+ * been started already.
+ * If CDAC == 0, we can not trust the CSAC value since it has
+ * not been updated, and can contain random number.
+ * Return the start address in case the DMA has not jet started.
+ * This is valid since in fact the DMA has not yet progressed.
+ */
+ cdac = p->dma_read(CDAC, lch);
+ if (likely(cdac))
+ offset = p->dma_read(CSAC, lch);
+ else
+ offset = p->dma_read(CSSA, lch);
+ }
if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
offset = p->dma_read(CSAC, lch);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index ee9f6eb..4278e3c 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -3,6 +3,12 @@
*
* OMAP Dual-Mode Timers
*
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
* Copyright (C) 2005 Nokia Corporation
* OMAP2 support by Juha Yrjola
* API improvements and OMAP2 clock framework support by Timo Teras
@@ -29,17 +35,17 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
#include <plat/dmtimer.h>
-#include <mach/irqs.h>
+#include <plat/common.h>
+#include <plat/omap-pm.h>
/* register offsets */
#define _OMAP_TIMER_ID_OFFSET 0x00
@@ -150,168 +156,144 @@
#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-struct omap_dm_timer {
- unsigned long phys_base;
- int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
- struct clk *iclk, *fclk;
-#endif
- void __iomem *io_base;
- unsigned reserved:1;
- unsigned enabled:1;
- unsigned posted:1;
-};
+/*
+ * OMAP4 IP revision has different register offsets
+ * for interrupt registers and functional registers.
+ */
+#define VERSION2_TIMER_WAKEUP_EN_REG_OFFSET 0x14
+#define VERSION2_TIMER_STAT_REG_OFFSET 0x10
-static int dm_timer_count;
-
-#ifdef CONFIG_ARCH_OMAP1
-static struct omap_dm_timer omap1_dm_timers[] = {
- { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
- { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
- { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
- { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
- { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
- { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
- { .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
- { .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
-};
+#define MAX_WRITE_PEND_WAIT 10000 /* 10ms timeout delay */
-static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
+static LIST_HEAD(omap_timer_list);
+static DEFINE_MUTEX(dm_timer_mutex);
-#else
-#define omap1_dm_timers NULL
-#define omap1_dm_timer_count 0
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct omap_dm_timer omap2_dm_timers[] = {
- { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
- { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
- { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
- { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
- { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
- { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
- { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
- { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
- { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
- { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
- { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
- { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
-};
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer: timer pointer over which read operation to perform
+ * @reg: lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
+ */
+static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
+{
+ int i = 0;
-static const char *omap2_dm_source_names[] __initdata = {
- "sys_ck",
- "func_32k_ck",
- "alt_ck",
- NULL
-};
+ if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+ reg += timer->func_offset;
+ else if (reg >= OMAP_TIMER_STAT_REG)
+ reg += timer->intr_offset;
-static struct clk *omap2_dm_source_clocks[3];
-static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
+ if (timer->posted) {
+ omap_test_timeout(!(readl(timer->io_base +
+ ((OMAP_TIMER_WRITE_PEND_REG +
+ timer->func_offset) & 0xff)) & (reg >> WPSHIFT)),
+ MAX_WRITE_PEND_WAIT, i);
-#else
-#define omap2_dm_timers NULL
-#define omap2_dm_timer_count 0
-#define omap2_dm_source_names NULL
-#define omap2_dm_source_clocks NULL
-#endif /* CONFIG_ARCH_OMAP2 */
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_dm_timer omap3_dm_timers[] = {
- { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
- { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
- { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
- { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
- { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
- { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
- { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
- { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
- { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
- { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
- { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
- { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
-};
+ if (WARN_ON_ONCE(i == MAX_WRITE_PEND_WAIT))
+ dev_err(&timer->pdev->dev, "read timeout.\n");
+ }
-static const char *omap3_dm_source_names[] __initdata = {
- "sys_ck",
- "omap_32k_fck",
- NULL
-};
+ return readl(timer->io_base + (reg & 0xff));
+}
-static struct clk *omap3_dm_source_clocks[2];
-static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer: timer pointer over which write operation is to perform
+ * @reg: lowest byte holds the register offset
+ * @value: data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
+ */
+static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
+ u32 value)
+{
+ int i = 0;
-#else
-#define omap3_dm_timers NULL
-#define omap3_dm_timer_count 0
-#define omap3_dm_source_names NULL
-#define omap3_dm_source_clocks NULL
-#endif /* CONFIG_ARCH_OMAP3 */
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct omap_dm_timer omap4_dm_timers[] = {
- { .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
- { .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
- { .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
- { .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
- { .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
- { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
- { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
- { .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
- { .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
- { .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
- { .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
- { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
-};
-static const char *omap4_dm_source_names[] __initdata = {
- "sys_clkin_ck",
- "sys_32k_ck",
- NULL
-};
-static struct clk *omap4_dm_source_clocks[2];
-static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
+ if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+ reg += timer->func_offset;
+ else if (reg >= OMAP_TIMER_STAT_REG)
+ reg += timer->intr_offset;
-#else
-#define omap4_dm_timers NULL
-#define omap4_dm_timer_count 0
-#define omap4_dm_source_names NULL
-#define omap4_dm_source_clocks NULL
-#endif /* CONFIG_ARCH_OMAP4 */
+ if (timer->posted) {
+ omap_test_timeout(!(readl(timer->io_base +
+ ((OMAP_TIMER_WRITE_PEND_REG +
+ timer->func_offset) & 0xff)) & (reg >> WPSHIFT)),
+ MAX_WRITE_PEND_WAIT, i);
-static struct omap_dm_timer *dm_timers;
-static const char **dm_source_names;
-static struct clk **dm_source_clocks;
+ if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
+ dev_err(&timer->pdev->dev, "write timeout.\n");
+ }
-static spinlock_t dm_timer_lock;
+ writel(value, timer->io_base + (reg & 0xff));
+}
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
- */
-static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
+static void omap_timer_save_context(struct omap_dm_timer *timer)
{
- if (timer->posted)
- while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
- cpu_relax();
- return readl(timer->io_base + (reg & 0xff));
+ timer->context.tiocp_cfg =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
+ timer->context.tistat =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG);
+ timer->context.tisr =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+ timer->context.tier =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_INT_EN_REG);
+ timer->context.twer =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
+ timer->context.tclr =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ timer->context.tcrr =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+ timer->context.tldr =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG);
+ timer->context.tmar =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
+ timer->context.tsicr =
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG);
}
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
- */
-static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
- u32 value)
+static void omap_timer_restore_context(struct omap_dm_timer *timer)
{
- if (timer->posted)
- while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
- cpu_relax();
- writel(value, timer->io_base + (reg & 0xff));
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG,
+ timer->context.tiocp_cfg);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_SYS_STAT_REG,
+ timer->context.tistat);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+ timer->context.tisr);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG,
+ timer->context.tier);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
+ timer->context.twer);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
+ timer->context.tclr);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
+ timer->context.tcrr);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
+ timer->context.tldr);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
+ timer->context.tmar);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
+ timer->context.tsicr);
+}
+
+static void __timer_enable(struct omap_dm_timer *timer)
+{
+ if (!timer->enabled) {
+ pm_runtime_get_sync(&timer->pdev->dev);
+ timer->enabled = 1;
+ }
+}
+
+static void __timer_disable(struct omap_dm_timer *timer)
+{
+ if (timer->enabled) {
+ pm_runtime_put_sync_suspend(&timer->pdev->dev);
+ timer->enabled = 0;
+ }
}
static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
@@ -332,58 +314,89 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
{
u32 l;
- if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
+ if (!timer->is_early_init)
+ __timer_enable(timer);
+
+ if (timer->pdev->id != 1) {
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
omap_dm_timer_wait_for_reset(timer);
}
- omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
l |= 0x02 << 3; /* Set to smart-idle mode */
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
- /* Enable autoidle on OMAP2 / OMAP3 */
- if (cpu_is_omap24xx() || cpu_is_omap34xx())
- l |= 0x1 << 0;
+ if (!timer->is_early_init)
+ __timer_disable(timer);
+}
- /*
- * Enable wake-up on OMAP2 CPUs.
- */
- if (cpu_class_is_omap2())
- l |= 1 << 2;
- omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
+{
+ int ret;
+
+ timer->fclk = clk_get(&timer->pdev->dev, "fck");
+ if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+ timer->fclk = NULL;
+ dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+ return -EINVAL;
+ }
+
+ if (unlikely(timer->is_early_init)) {
+ ret = clk_enable(timer->fclk);
+ if (ret) {
+ clk_put(timer->fclk);
+ return -EINVAL;
+ }
+ goto end;
+ }
+
+ if (timer->needs_manual_reset)
+ omap_dm_timer_reset(timer);
+
+ omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+end:
+ if (!timer->is_early_init)
+ __timer_enable(timer);
/* Match hardware reset default of posted mode */
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
OMAP_TIMER_CTRL_POSTED);
- timer->posted = 1;
-}
-static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
-{
- omap_dm_timer_enable(timer);
- omap_dm_timer_reset(timer);
+ if (!timer->is_early_init)
+ __timer_disable(timer);
+
+ timer->posted = 1;
+ return 0;
}
struct omap_dm_timer *omap_dm_timer_request(void)
{
- struct omap_dm_timer *timer = NULL;
- unsigned long flags;
- int i;
+ struct omap_dm_timer *timer = NULL, *t;
+ int ret;
- spin_lock_irqsave(&dm_timer_lock, flags);
- for (i = 0; i < dm_timer_count; i++) {
- if (dm_timers[i].reserved)
+ mutex_lock(&dm_timer_mutex);
+ list_for_each_entry(t, &omap_timer_list, node) {
+ if (t->reserved)
continue;
- timer = &dm_timers[i];
+ timer = t;
timer->reserved = 1;
+ timer->enabled = 0;
break;
}
- spin_unlock_irqrestore(&dm_timer_lock, flags);
+ mutex_unlock(&dm_timer_mutex);
- if (timer != NULL)
- omap_dm_timer_prepare(timer);
+ if (!timer) {
+ pr_debug("%s: free timer not available.\n", __func__);
+ return NULL;
+ }
+ ret = omap_dm_timer_prepare(timer);
+ if (ret) {
+ timer->reserved = 0;
+ return NULL;
+ }
return timer;
}
@@ -391,74 +404,88 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request);
struct omap_dm_timer *omap_dm_timer_request_specific(int id)
{
- struct omap_dm_timer *timer;
- unsigned long flags;
+ struct omap_dm_timer *timer = NULL, *t;
+ int ret;
+
+ mutex_lock(&dm_timer_mutex);
+ list_for_each_entry(t, &omap_timer_list, node) {
+ if (t->pdev->id == id && !t->reserved) {
+ timer = t;
+ timer->reserved = 1;
+ timer->enabled = 0;
+ break;
+ }
+ }
+ mutex_unlock(&dm_timer_mutex);
- spin_lock_irqsave(&dm_timer_lock, flags);
- if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
- spin_unlock_irqrestore(&dm_timer_lock, flags);
- printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
- __FILE__, __LINE__, __func__, id);
- dump_stack();
+ if (!timer) {
+ pr_debug("%s: timer%d not available.\n", __func__, id);
+ return NULL;
+ }
+ ret = omap_dm_timer_prepare(timer);
+ if (ret) {
+ timer->reserved = 0;
return NULL;
}
-
- timer = &dm_timers[id-1];
- timer->reserved = 1;
- spin_unlock_irqrestore(&dm_timer_lock, flags);
-
- omap_dm_timer_prepare(timer);
return timer;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
-void omap_dm_timer_free(struct omap_dm_timer *timer)
+int omap_dm_timer_free(struct omap_dm_timer *timer)
{
- omap_dm_timer_enable(timer);
- omap_dm_timer_reset(timer);
- omap_dm_timer_disable(timer);
+ unsigned long flags;
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (!timer->reserved) {
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return -EINVAL;
+ }
+
+ __timer_disable(timer);
+ clk_put(timer->fclk);
- WARN_ON(!timer->reserved);
timer->reserved = 0;
+ timer->context_saved = false;
+
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_free);
-void omap_dm_timer_enable(struct omap_dm_timer *timer)
+int omap_dm_timer_enable(struct omap_dm_timer *timer)
{
- if (timer->enabled)
- return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- clk_enable(timer->fclk);
- clk_enable(timer->iclk);
- }
-#endif
+ unsigned long flags;
+ if (!timer)
+ return -EINVAL;
- timer->enabled = 1;
+ spin_lock_irqsave(&timer->lock, flags);
+ __timer_enable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
-void omap_dm_timer_disable(struct omap_dm_timer *timer)
+int omap_dm_timer_disable(struct omap_dm_timer *timer)
{
- if (!timer->enabled)
- return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- clk_disable(timer->iclk);
- clk_disable(timer->fclk);
- }
-#endif
+ unsigned long flags;
+ if (!timer)
+ return -EINVAL;
- timer->enabled = 0;
+ spin_lock_irqsave(&timer->lock, flags);
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
{
- return timer->irq;
+ if (timer)
+ return timer->irq;
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
@@ -470,24 +497,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
*/
__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
{
- int i;
+ int i = 0;
+ struct omap_dm_timer *timer = NULL;
/* If ARMXOR cannot be idled this function call is unnecessary */
if (!(inputmask & (1 << 1)))
return inputmask;
/* If any active timer is using ARMXOR return modified mask */
- for (i = 0; i < dm_timer_count; i++) {
+ mutex_lock(&dm_timer_mutex);
+ list_for_each_entry(timer, &omap_timer_list, node) {
+
u32 l;
- l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (l & OMAP_TIMER_CTRL_ST) {
if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
inputmask &= ~(1 << 1);
else
inputmask &= ~(1 << 2);
}
+ i++;
}
+ mutex_unlock(&dm_timer_mutex);
return inputmask;
}
@@ -497,7 +529,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
{
- return timer->fclk;
+ if (timer)
+ return timer->fclk;
+ return NULL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
@@ -511,75 +545,116 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
#endif
-void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+int omap_dm_timer_trigger(struct omap_dm_timer *timer)
{
- omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->enabled) {
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
-void omap_dm_timer_start(struct omap_dm_timer *timer)
+int omap_dm_timer_start(struct omap_dm_timer *timer)
{
u32 l;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->loses_context) {
+ __timer_enable(timer);
+ if (omap_pm_was_context_lost(&timer->pdev->dev) &&
+ timer->context_saved) {
+ omap_timer_restore_context(timer);
+ timer->context_saved = false;
+ }
+ }
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (!(l & OMAP_TIMER_CTRL_ST)) {
l |= OMAP_TIMER_CTRL_ST;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_start);
-void omap_dm_timer_stop(struct omap_dm_timer *timer)
+int omap_dm_timer_stop(struct omap_dm_timer *timer)
{
u32 l;
+ struct dmtimer_platform_data *pdata;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (!timer->enabled) {
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return -EINVAL;
+ }
+ pdata = timer->pdev->dev.platform_data;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (l & OMAP_TIMER_CTRL_ST) {
l &= ~0x1;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-#ifdef CONFIG_ARCH_OMAP2PLUS
- /* Readback to make sure write has completed */
- omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
- /*
- * Wait for functional clock period x 3.5 to make sure that
- * timer is stopped
- */
- udelay(3500000 / clk_get_rate(timer->fclk) + 1);
-#endif
+
+ if (!pdata->needs_manual_reset) {
+ /* Readback to make sure write has completed */
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ /*
+ * Wait for functional clock period x 3.5 to make
+ * sure that timer is stopped
+ */
+ udelay(3500000 / clk_get_rate(timer->fclk) + 1);
+ }
}
/* Ack possibly pending interrupt */
omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
OMAP_TIMER_INT_OVERFLOW);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
-
-#ifdef CONFIG_ARCH_OMAP1
-
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
- int n = (timer - dm_timers) << 1;
- u32 l;
-
- l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
- l |= source << n;
- omap_writel(l, MOD_CONF_CTRL_1);
+ if (timer->loses_context) {
+ omap_timer_save_context(timer);
+ timer->context_saved = true;
+ __timer_disable(timer);
+ }
+ spin_unlock_irqrestore(&timer->lock, flags);
return 0;
}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
-
-#else
+EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
- int ret = -EINVAL;
+ int ret;
+ struct dmtimer_platform_data *pdata;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
if (source < 0 || source >= 3)
return -EINVAL;
- clk_disable(timer->fclk);
- ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
- clk_enable(timer->fclk);
+ spin_lock_irqsave(&timer->lock, flags);
+ pdata = timer->pdev->dev.platform_data;
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+
+ /* change the timer clock source */
+ ret = pdata->set_timer_src(timer->pdev, source);
/*
* When the functional clock disappears, too quick writes seem
@@ -591,13 +666,17 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
-#endif
-
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
unsigned int load)
{
u32 l;
+ unsigned long flags;
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ __timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload)
l |= OMAP_TIMER_CTRL_AR;
@@ -607,14 +686,30 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
-/* Optimized set_load which removes costly spin wait in timer_start */
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
unsigned int load)
{
u32 l;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->loses_context) {
+ __timer_enable(timer);
+ if (omap_pm_was_context_lost(&timer->pdev->dev) &&
+ timer->context_saved) {
+ omap_timer_restore_context(timer);
+ timer->context_saved = false;
+ }
+ }
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload) {
@@ -627,14 +722,22 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
unsigned int match)
{
u32 l;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
+ __timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (enable)
l |= OMAP_TIMER_CTRL_CE;
@@ -642,14 +745,23 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
l &= ~OMAP_TIMER_CTRL_CE;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
int toggle, int trigger)
{
u32 l;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
+ __timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -659,13 +771,22 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
l |= OMAP_TIMER_CTRL_PT;
l |= trigger << 10;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
{
u32 l;
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
+ __timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -673,58 +794,115 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
l |= prescaler << 2;
}
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
+ unsigned long flags;
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (!timer->is_early_init)
+ __timer_enable(timer);
+
omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
+
+ if (!timer->is_early_init)
+ __timer_disable(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
- unsigned int l;
+ unsigned long flags;
+ unsigned int ret;
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+ if (WARN_ON(!timer))
+ return -EINVAL;
- return l;
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->is_early_init || timer->enabled) {
+ ret = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return ret;
+ }
+ spin_unlock_irqrestore(&timer->lock, flags);
+ WARN_ON(!timer->enabled);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
- omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->is_early_init || timer->enabled) {
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
- unsigned int l;
+ unsigned long flags;
+ unsigned int ret;
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+ if (WARN_ON(!timer))
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->is_early_init || timer->enabled) {
+ ret = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return ret;
+ }
- return l;
+ spin_unlock_irqrestore(&timer->lock, flags);
+ WARN_ON(!timer->enabled);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
{
- omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+ unsigned long flags;
+
+ if (!timer)
+ return -EINVAL;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ if (timer->is_early_init || timer->enabled) {
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
int omap_dm_timers_active(void)
{
- int i;
-
- for (i = 0; i < dm_timer_count; i++) {
- struct omap_dm_timer *timer;
-
- timer = &dm_timers[i];
+ struct omap_dm_timer *timer;
+ list_for_each_entry(timer, &omap_timer_list, node) {
if (!timer->enabled)
continue;
@@ -737,61 +915,146 @@ int omap_dm_timers_active(void)
}
EXPORT_SYMBOL_GPL(omap_dm_timers_active);
-int __init omap_dm_timer_init(void)
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev: pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
{
+ int ret;
struct omap_dm_timer *timer;
- int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */
+ struct resource *mem, *irq, *ioarea;
+ struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
- if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
return -ENODEV;
+ }
- spin_lock_init(&dm_timer_lock);
-
- if (cpu_class_is_omap1()) {
- dm_timers = omap1_dm_timers;
- dm_timer_count = omap1_dm_timer_count;
- map_size = SZ_2K;
- } else if (cpu_is_omap24xx()) {
- dm_timers = omap2_dm_timers;
- dm_timer_count = omap2_dm_timer_count;
- dm_source_names = omap2_dm_source_names;
- dm_source_clocks = omap2_dm_source_clocks;
- } else if (cpu_is_omap34xx()) {
- dm_timers = omap3_dm_timers;
- dm_timer_count = omap3_dm_timer_count;
- dm_source_names = omap3_dm_source_names;
- dm_source_clocks = omap3_dm_source_clocks;
- } else if (cpu_is_omap44xx()) {
- dm_timers = omap4_dm_timers;
- dm_timer_count = omap4_dm_timer_count;
- dm_source_names = omap4_dm_source_names;
- dm_source_clocks = omap4_dm_source_clocks;
- }
-
- if (cpu_class_is_omap2())
- for (i = 0; dm_source_names[i] != NULL; i++)
- dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
-
- if (cpu_is_omap243x())
- dm_timers[0].phys_base = 0x49018000;
-
- for (i = 0; i < dm_timer_count; i++) {
- timer = &dm_timers[i];
-
- /* Static mapping, never released */
- timer->io_base = ioremap(timer->phys_base, map_size);
- BUG_ON(!timer->io_base);
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- char clk_name[16];
- sprintf(clk_name, "gpt%d_ick", i + 1);
- timer->iclk = clk_get(NULL, clk_name);
- sprintf(clk_name, "gpt%d_fck", i + 1);
- timer->fclk = clk_get(NULL, clk_name);
- }
-#endif
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(!irq)) {
+ dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+ return -ENODEV;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!mem)) {
+ dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+ return -ENODEV;
+ }
+
+ ioarea = request_mem_region(mem->start, resource_size(mem),
+ pdev->name);
+ if (!ioarea) {
+ dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+ return -EBUSY;
+ }
+
+ timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+ if (!timer) {
+ dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_release_ioregion;
+ }
+
+ timer->io_base = ioremap(mem->start, resource_size(mem));
+ if (!timer->io_base) {
+ dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+ ret = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
+ timer->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
+ timer->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
+ }
+
+ timer->irq = irq->start;
+ timer->pdev = pdev;
+ timer->is_early_init = pdata->is_early_init;
+ timer->needs_manual_reset = pdata->needs_manual_reset;
+ timer->loses_context = pdata->loses_context;
+
+ spin_lock_init(&timer->lock);
+ /* Skip pm_runtime_enable during early boot and for OMAP1 */
+ if (!pdata->is_early_init && !pdata->needs_manual_reset) {
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_irq_safe(&pdev->dev);
}
+ /* add the timer element to the list */
+ mutex_lock(&dm_timer_mutex);
+ list_add_tail(&timer->node, &omap_timer_list);
+ mutex_unlock(&dm_timer_mutex);
+
+ dev_dbg(&pdev->dev, "Device Probed.\n");
+
return 0;
+
+err_free_mem:
+ kfree(timer);
+
+err_release_ioregion:
+ release_mem_region(mem->start, resource_size(mem));
+
+ return ret;
+}
+
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev: pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+ struct omap_dm_timer *timer;
+ int ret = -EINVAL;
+
+ mutex_lock(&dm_timer_mutex);
+ list_for_each_entry(timer, &omap_timer_list, node) {
+ if (timer->pdev->id == pdev->id) {
+ list_del(&timer->node);
+ kfree(timer);
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&dm_timer_mutex);
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+ .probe = omap_dm_timer_probe,
+ .remove = omap_dm_timer_remove,
+ .driver = {
+ .name = "omap_timer",
+ },
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+ return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+ platform_driver_unregister(&omap_dm_timer_driver);
}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
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..c8a65ba 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;
@@ -96,5 +97,6 @@ extern struct device *omap2_get_mpuss_device(void);
extern struct device *omap2_get_iva_device(void);
extern struct device *omap2_get_l3_device(void);
extern struct device *omap4_get_dsp_device(void);
+extern struct device *omap4_get_fdif_device(void);
#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 8198bb6..6c9fc01 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -45,7 +45,7 @@
int omap_type(void);
struct omap_chip_id {
- u16 oc;
+ u32 oc;
u8 type;
};
@@ -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,10 @@ 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))
+#define OMAP4460_REV_ES1_1 (OMAP446X_CLASS | (0x11 << 8))
+
/*
* omap_chip bits
*
@@ -439,14 +448,21 @@ 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_OMAP4460ES1_1 (1 << 16)
#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 | \
+ CHIP_IS_OMAP4460ES1_1)
+
+#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
@@ -494,4 +510,23 @@ OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
OMAP3_HAS_FEATURE(sdrc, SDRC)
+/*
+ * Runtime detection of OMAP4 features
+ */
+extern u32 omap4_features;
+
+#define OMAP4_HAS_MPU_1GHZ BIT(0)
+#define OMAP4_HAS_MPU_1_2GHZ BIT(1)
+#define OMAP4_HAS_MPU_1_5GHZ BIT(2)
+
+#define OMAP4_HAS_FEATURE(feat, flag) \
+static inline unsigned int omap4_has_ ##feat(void) \
+{ \
+ return omap4_features & OMAP4_HAS_ ##flag; \
+} \
+
+OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
+OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
+OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
+
#endif
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index d6c70d2..aaa676f 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -35,6 +35,7 @@
#ifndef __ASM_ARCH_DMTIMER_H
#define __ASM_ARCH_DMTIMER_H
+#include <linux/spinlock_types.h>
/* clock sources */
#define OMAP_TIMER_SRC_SYS_CLK 0x00
#define OMAP_TIMER_SRC_32_KHZ 0x01
@@ -55,41 +56,103 @@
* in OMAP4 can be distinguished.
*/
#define OMAP_TIMER_IP_VERSION_1 0x1
-struct omap_dm_timer;
+#define OMAP_TIMER_IP_VERSION_2 0x2
+
+struct omap_secure_timer_dev_attr {
+ bool is_secure_timer;
+};
+
+struct timer_regs {
+ u32 tidr;
+ u32 tiocp_cfg;
+ u32 tistat;
+ u32 tisr;
+ u32 tier;
+ u32 twer;
+ u32 tclr;
+ u32 tcrr;
+ u32 tldr;
+ u32 ttrg;
+ u32 twps;
+ u32 tmar;
+ u32 tcar1;
+ u32 tsicr;
+ u32 tcar2;
+ u32 tpir;
+ u32 tnir;
+ u32 tcvr;
+ u32 tocr;
+ u32 towr;
+};
+
+struct omap_dm_timer {
+ int irq;
+ struct clk *fclk;
+ void __iomem *io_base;
+ unsigned reserved:1;
+ unsigned enabled:1;
+ unsigned posted:1;
+ unsigned is_early_init:1;
+ unsigned needs_manual_reset:1;
+ spinlock_t lock;
+ u8 func_offset;
+ u8 intr_offset;
+ bool loses_context;
+ bool context_saved;
+ u32 ctx_loss_count;
+ struct timer_regs context;
+ struct platform_device *pdev;
+ struct list_head node;
+
+};
+
extern struct omap_dm_timer *gptimer_wakeup;
extern struct sys_timer omap_timer;
struct clk;
-int omap_dm_timer_init(void);
+struct dmtimer_platform_data {
+ int (*set_timer_src)(struct platform_device *pdev, int source);
+ int timer_ip_type;
+ u32 is_early_init:1;
+ u32 needs_manual_reset:1;
+ bool loses_context;
+
+};
struct omap_dm_timer *omap_dm_timer_request(void);
struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
-void omap_dm_timer_free(struct omap_dm_timer *timer);
-void omap_dm_timer_enable(struct omap_dm_timer *timer);
-void omap_dm_timer_disable(struct omap_dm_timer *timer);
+int omap_dm_timer_free(struct omap_dm_timer *timer);
+int omap_dm_timer_enable(struct omap_dm_timer *timer);
+int omap_dm_timer_disable(struct omap_dm_timer *timer);
int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
-void omap_dm_timer_trigger(struct omap_dm_timer *timer);
-void omap_dm_timer_start(struct omap_dm_timer *timer);
-void omap_dm_timer_stop(struct omap_dm_timer *timer);
+int omap_dm_timer_trigger(struct omap_dm_timer *timer);
+int omap_dm_timer_start(struct omap_dm_timer *timer);
+int omap_dm_timer_stop(struct omap_dm_timer *timer);
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
-
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+ unsigned int value);
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer,
+ int autoreload, unsigned int value);
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+ unsigned int match);
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+ int toggle, int trigger);
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
+
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+ unsigned int value);
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer,
+ unsigned int value);
int omap_dm_timers_active(void);
diff --git a/arch/arm/plat-omap/include/plat/dsp.h b/arch/arm/plat-omap/include/plat/dsp.h
index 9c604b3..14f1228 100644
--- a/arch/arm/plat-omap/include/plat/dsp.h
+++ b/arch/arm/plat-omap/include/plat/dsp.h
@@ -24,8 +24,12 @@ struct omap_dsp_platform_data {
#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE)
extern void omap_dsp_reserve_sdram_memblock(void);
+phys_addr_t omap_dsp_get_mempool_size(void);
+phys_addr_t omap_dsp_get_mempool_base(void);
#else
static inline void omap_dsp_reserve_sdram_memblock(void) { }
+static inline phys_addr_t omap_dsp_get_mempool_size(void) { return 0; }
+static inline phys_addr_t omap_dsp_get_mempool_base(void) { return 0; }
#endif
#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..d41b73a
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/dsscomp.h
@@ -0,0 +1,25 @@
+#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(struct omap_overlay_manager *mgr);
+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_delayed_apply(dsscomp_t comp);
+void dsscomp_drop(dsscomp_t c);
+
+struct tiler_pa_info;
+int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d,
+ struct tiler_pa_info **pas,
+ bool early_callback,
+ void (*cb_fn)(void *, int), void *cb_arg);
+#endif
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index ec97e00..90eae5c 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -162,35 +162,61 @@
IH_MPUIO_BASE + ((nr) & 0x0f) : \
IH_GPIO_BASE + (nr))
-#define METHOD_MPUIO 0
-#define METHOD_GPIO_1510 1
-#define METHOD_GPIO_1610 2
-#define METHOD_GPIO_7XX 3
-#define METHOD_GPIO_24XX 5
-#define METHOD_GPIO_44XX 6
-
struct omap_gpio_dev_attr {
int bank_width; /* GPIO bank width */
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
};
+struct omap_gpio_reg_offs {
+ u16 revision;
+ u16 direction;
+ u16 datain;
+ u16 dataout;
+ u16 set_dataout;
+ u16 clr_dataout;
+ u16 irqstatus;
+ u16 irqstatus2;
+ u16 irqenable;
+ u16 irqenable2;
+ u16 set_irqenable;
+ u16 clr_irqenable;
+ u16 debounce;
+ u16 debounce_en;
+ u16 ctrl;
+ u16 wkup_status;
+ u16 wkup_clear;
+ u16 wkup_set;
+ u16 leveldetect0;
+ u16 leveldetect1;
+ u16 risingdetect;
+ u16 fallingdetect;
+ u16 irqctrl;
+ u16 edgectrl1;
+ u16 edgectrl2;
+ /* Not applicable for OMAP2+ as hwmod layer takes care of sysconfig */
+ u16 sysconfig;
+ u16 pinctrl;
+
+ bool irqenable_inv;
+};
+
struct omap_gpio_platform_data {
u16 virtual_irq_start;
- int bank_type;
int bank_width; /* GPIO bank width */
int bank_stride; /* Only needed for omap1 MPUIO */
+ bool suspend_support; /* If Bank supports suspend/resume operations */
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
-};
+ bool loses_context; /* whether the bank would ever lose context */
+ bool is_mpuio; /* whether the bank is of type MPUIO */
+ u32 non_wakeup_gpios;
-/* TODO: Analyze removing gpio_bank_count usage from driver code */
-extern int gpio_bank_count;
+ struct omap_gpio_reg_offs *regs;
+};
-extern void omap2_gpio_prepare_for_idle(int off_mode);
-extern void omap2_gpio_resume_after_idle(void);
+extern int omap2_gpio_prepare_for_idle(int off_mode, bool suspend);
+extern void omap2_gpio_resume_after_idle(int off_mode);
extern void omap_set_gpio_debounce(int gpio, int enable);
extern void omap_set_gpio_debounce_time(int gpio, int enable);
-extern void omap_gpio_save_context(void);
-extern void omap_gpio_restore_context(void);
/*-------------------------------------------------------------------------*/
/* Wrappers for "new style" GPIO calls, using the new infrastructure
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 1527929..d668790 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -148,8 +148,8 @@ extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
unsigned int u32_count, int is_write);
extern int gpmc_prefetch_reset(int cs);
-extern void omap3_gpmc_save_context(void);
-extern void omap3_gpmc_restore_context(void);
+extern void omap_gpmc_save_context(void);
+extern void omap_gpmc_restore_context(void);
extern int gpmc_read_status(int cmd);
extern int gpmc_cs_configure(int cs, int cmd, int wval);
extern int gpmc_nand_read(int cs, int cmd);
diff --git a/arch/arm/plat-omap/include/plat/gpu.h b/arch/arm/plat-omap/include/plat/gpu.h
new file mode 100644
index 0000000..0a6313b
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/gpu.h
@@ -0,0 +1,39 @@
+/*
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef OMAP_GPU_H
+#define OMAP_GPU_H
+
+#include <plat/omap-pm.h>
+#include <linux/platform_device.h>
+
+struct gpu_platform_data {
+
+ /* Number of overdrive frequencies */
+ unsigned int ovfreqs;
+
+ void (*set_min_bus_tput)(struct device *dev, u8 agent_id,
+ unsigned long r);
+ int (*device_scale) (struct device *req_dev, struct device *target_dev,
+ unsigned long rate);
+ 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/io.h b/arch/arm/plat-omap/include/plat/io.h
index d72ec85..a2f7d31 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -228,12 +228,12 @@
#define OMAP44XX_EMIF2_PHYS OMAP44XX_EMIF2_BASE
/* 0x4d000000 --> 0xfd200000 */
-#define OMAP44XX_EMIF2_VIRT (OMAP44XX_EMIF2_PHYS + OMAP4_L3_PER_IO_OFFSET)
+#define OMAP44XX_EMIF2_VIRT (OMAP44XX_EMIF1_VIRT + SZ_1M)
#define OMAP44XX_EMIF2_SIZE SZ_1M
#define OMAP44XX_DMM_PHYS OMAP44XX_DMM_BASE
/* 0x4e000000 --> 0xfd300000 */
-#define OMAP44XX_DMM_VIRT (OMAP44XX_DMM_PHYS + OMAP4_L3_PER_IO_OFFSET)
+#define OMAP44XX_DMM_VIRT (OMAP44XX_EMIF2_VIRT + SZ_1M)
#define OMAP44XX_DMM_SIZE SZ_1M
/*
* ----------------------------------------------------------------------------
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 174f1b9..ed33ddf 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -13,6 +13,8 @@
#ifndef __MACH_IOMMU_H
#define __MACH_IOMMU_H
+#include <linux/pm_qos_params.h>
+
struct iotlb_entry {
u32 da;
u32 pa;
@@ -28,7 +30,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 +54,10 @@ struct iommu {
void *ctx; /* iommu context: registres saved area */
u32 da_start;
u32 da_end;
+ struct platform_device *pdev;
+ struct pm_qos_request_list *qos_request;
+ void *secure_ttb;
+ bool secure_mode;
};
struct cr_regs {
@@ -104,10 +109,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 */
@@ -174,6 +181,8 @@ extern int iommu_set_isr(const char *name,
void *priv),
void *isr_priv);
+extern int iommu_set_secure(const char *name, bool enable, void *data);
+
extern void iommu_save_ctx(struct iommu *obj);
extern void iommu_restore_ctx(struct iommu *obj);
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 10ad05f..45b2e36 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -36,6 +36,7 @@
#define MMU_READ_CAM 0x68
#define MMU_READ_RAM 0x6c
#define MMU_EMU_FAULT_AD 0x70
+#define MMU_GP_REG 0x88
#define MMU_REG_SIZE 256
diff --git a/arch/arm/plat-omap/include/plat/irqs-44xx.h b/arch/arm/plat-omap/include/plat/irqs-44xx.h
index 518322c..78839f1 100644
--- a/arch/arm/plat-omap/include/plat/irqs-44xx.h
+++ b/arch/arm/plat-omap/include/plat/irqs-44xx.h
@@ -141,4 +141,13 @@
#define OMAP44XX_IRQ_KBD_CTL (120 + OMAP44XX_IRQ_GIC_START)
#define OMAP44XX_IRQ_UNIPRO1 (124 + OMAP44XX_IRQ_GIC_START)
+/*
+ * GIC interrupts 54, 55, 60, 105, 106, 121, 122, 123, 125, and 127 are tied
+ * low, and can be repurposed as SW triggered IRQs
+ */
+#define OMAP44XX_IRQ_FIQ_DEBUGGER (54 + OMAP44XX_IRQ_GIC_START)
+#define OMAP44XX_IRQ_THERMAL_PROXY (55 + OMAP44XX_IRQ_GIC_START)
+#define OMAP44XX_IRQ_CPUIDLE_POKE0 (60 + OMAP44XX_IRQ_GIC_START)
+#define OMAP44XX_IRQ_CPUIDLE_POKE1 (105 + OMAP44XX_IRQ_GIC_START)
+
#endif
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/mcasp.h b/arch/arm/plat-omap/include/plat/mcasp.h
new file mode 100644
index 0000000..aead0a0
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/mcasp.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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_MCASP_H__
+#define __OMAP_PLAT_MCASP_H__
+
+#include <linux/platform_device.h>
+
+/* The SPDIF bit clock is derived from the McASP functional clock.
+ * The McASP has two programmable clock dividers (aclkxdiv and
+ * ahclkxdiv) that are configured via the registers MCASP_ACLKXCTL
+ * and MCASP_AHCLKXCTL. For SPDIF the bit clock frequency should be
+ * 128 * sample rate freq. Therefore...
+ *
+ * McASP functional clock = aclkxdiv * ahclkxdiv * 128 * sample rate
+ *
+ * For each sample rate supported the user must define the aclkxdiv
+ * and ahclkxdiv values that are passed to the McASP driver via the
+ * following structure. The McASP functional clock frequency can be
+ * configured also, and this is pass to the McASP driver via the
+ * omap_mcasp_platform_data structure below.
+ */
+struct omap_mcasp_configs {
+ unsigned int sampling_rate;
+ u16 aclkxdiv;
+ u16 ahclkxdiv;
+};
+
+struct omap_mcasp_platform_data {
+ unsigned long mcasp_fclk_rate;
+ struct omap_mcasp_configs *mcasp_configs;
+ unsigned int num_configs;
+};
+
+void omap_init_mcasp(struct omap_mcasp_platform_data *pdata);
+
+#endif
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..19ae03b
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/mcpdm.h
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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 {
+ bool (*was_context_lost)(struct device *dev);
+};
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/mcspi.h b/arch/arm/plat-omap/include/plat/mcspi.h
index 3d51b18..091caa1 100644
--- a/arch/arm/plat-omap/include/plat/mcspi.h
+++ b/arch/arm/plat-omap/include/plat/mcspi.h
@@ -21,6 +21,8 @@ struct omap2_mcspi_device_config {
/* Do we want one channel enabled at the same time? */
unsigned single_channel:1;
+ /* Swap data lines */
+ unsigned swap_datalines;
};
#endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index c7b8741..b95aabd 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/mmc/host.h>
+#include <asm/mach/mmc.h>
#include <plat/board.h>
#define OMAP15XX_NR_MMC 1
@@ -60,9 +61,6 @@ struct omap_mmc_platform_data {
int (*suspend)(struct device *dev, int slot);
int (*resume)(struct device *dev, int slot);
- /* Return context loss count due to PM states changing */
- int (*get_context_loss_count)(struct device *dev);
-
u64 dma_mask;
/* Integrating attributes from the omap_hwmod layer */
@@ -108,8 +106,9 @@ struct omap_mmc_platform_data {
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) */
@@ -146,6 +145,9 @@ struct omap_mmc_platform_data {
int card_detect_irq;
int (*card_detect)(struct device *dev, int slot);
+ /* Additional mmc configuration */
+ struct mmc_platform_data mmc_data;
+
unsigned int ban_openended:1;
} slots[OMAP_MMC_MAX_SLOTS];
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index c0a7520..2efbff5 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);
/**
@@ -337,24 +343,26 @@ unsigned long omap_pm_cpu_get_freq(void);
*/
/**
- * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx
- * @dev: struct device *
- *
- * This function returns the number of times that the device @dev has
- * lost its internal context. This generally occurs on a powerdomain
- * transition to OFF. Drivers use this as an optimization to avoid restoring
- * context if the device hasn't lost it. To use, drivers should initially
- * call this in their context save functions and store the result. Early in
- * the driver's context restore function, the driver should call this function
- * again, and compare the result to the stored counter. If they differ, the
- * 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 zero upon error.
+ * omap_pm_was_context_lost - return true if a device lost hw context
+ *
+ * This function returns a bool value indication if a device has lost
+ * its context. Depending on the HW implementation of the device, Context
+ * can be lost in OFF or OSWR. This function reads and *CLEARS* the context
+ * lost registers for the device.
+ */
+bool omap_pm_was_context_lost(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.
*/
-u32 omap_pm_get_dev_context_loss_count(struct device *dev);
+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);
+extern bool off_mode_enabled;
+
#endif
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 2682043..2fbb5f0 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -36,13 +36,14 @@
/* WER = 0x7F
* Enable module level wakeup in WER reg
*/
-#define OMAP_UART_WER_MOD_WKUP 0X7F
+#define OMAP2_UART_WER_MOD_WKUP 0X7F
+#define OMAP4_UART_WER_MOD_WKUP 0XFF
/* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX 0x04
+#define OMAP_UART_SW_TX 0x8
/* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX 0x04
+#define OMAP_UART_SW_RX 0x2
#define OMAP_UART_SYSC_RESET 0X07
#define OMAP_UART_TCR_TRIG 0X0F
@@ -51,18 +52,51 @@
#define OMAP_UART_DMA_CH_FREE -1
-#define RX_TIMEOUT (3 * HZ)
+#define RX_TIMEOUT (3 * HZ) /* RX DMA timeout (jiffies) */
+
+#define DEFAULT_RXDMA_TIMEOUT (3 * HZ) /* RX DMA timeout (jiffies) */
+#define DEFAULT_RXDMA_POLLRATE 1 /* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
+#define DEFAULT_AUTOSUSPEND_DELAY 3000 /* Runtime autosuspend (msecs)*/
+
+/*
+ * (Errata i659) - From OMAP4430 ES 2.0 onwards set
+ * tx_threshold while using UART in DMA Mode
+ * and ensure tx_threshold + tx_trigger <= 63
+ */
+#define UART_MDR3 0x20
+#define UART_TX_DMA_THRESHOLD 0x21
+#define SET_DMA_TX_THRESHOLD BIT(2)
+/* Setting TX Threshold Level to 62 */
+#define TX_FIFO_THR_LVL 0x3E
+
#define OMAP_MAX_HSUART_PORTS 4
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+#define UART_ERRATA_i202_MDR1_ACCESS BIT(0)
+#define OMAP4_UART_ERRATA_i659_TX_THR BIT(1)
+
struct omap_uart_port_info {
- bool dma_enabled; /* To specify DMA Mode */
+ int dma_rx_buf_size;/* DMA Rx Buffer Size */
+ int dma_rx_timeout; /* DMA RX timeout */
+ unsigned int idle_timeout; /* Omap Uart Idle Time out */
+ int use_dma; /* DMA Enable / Disable */
unsigned int uartclk; /* UART clock rate */
- void __iomem *membase; /* ioremap cookie or NULL */
- resource_size_t mapbase; /* resource base */
- unsigned long irqflags; /* request_irq flags */
upf_t flags; /* UPF_* flags */
+ unsigned int errata;
+ unsigned int console_uart;
+ u16 wer; /* Module Wakeup register */
+ unsigned int dma_rx_poll_rate; /* DMA RX poll_rate */
+ unsigned int auto_sus_timeout; /* Auto_suspend timeout */
+ unsigned rts_mux_driver_control:1;
+
+ void (*enable_wakeup)(struct platform_device *, bool);
+ bool (*chk_wakeup)(struct platform_device *);
+ void (*wake_peer)(struct uart_port *);
+ void __iomem *wk_st;
+ void __iomem *wk_en;
+ u32 wk_mask;
};
struct uart_omap_dma {
@@ -86,8 +120,9 @@ struct uart_omap_dma {
spinlock_t rx_lock;
/* timer to poll activity on rx dma */
struct timer_list rx_timer;
- int rx_buf_size;
- int rx_timeout;
+ unsigned int rx_buf_size;
+ unsigned int rx_poll_rate;
+ unsigned int rx_timeout;
};
struct uart_omap_port {
@@ -100,8 +135,13 @@ struct uart_omap_port {
unsigned char mcr;
unsigned char fcr;
unsigned char efr;
+ unsigned char dll;
+ unsigned char dlh;
+ unsigned char mdr1;
+ unsigned char wer;
int use_dma;
+ bool suspended;
/*
* Some bits in registers are cleared on a read, so they must
* be saved whenever the register is read but the bits will not
@@ -110,7 +150,16 @@ struct uart_omap_port {
unsigned int lsr_break_flag;
unsigned char msr_saved_flags;
char name[20];
+ unsigned int console_lock;
unsigned long port_activity;
+ int context_loss_cnt;
+ /* RTS control via driver */
+ unsigned rts_mux_driver_control:1;
+ unsigned rts_pullup_in_suspend:1;
+
+ unsigned int errata;
+ void (*enable_wakeup)(struct platform_device *, bool);
+ bool (*chk_wakeup)(struct platform_device *);
+ void (*wake_peer)(struct uart_port *);
};
-
#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..f6da497 100644
--- a/arch/arm/plat-omap/include/plat/omap44xx.h
+++ b/arch/arm/plat-omap/include/plat/omap44xx.h
@@ -22,6 +22,9 @@
#define L4_PER_44XX_BASE 0x48000000
#define L4_EMU_44XX_BASE 0x54000000
#define L3_44XX_BASE 0x44000000
+#define L3_44XX_BASE_CLK1 L3_44XX_BASE
+#define L3_44XX_BASE_CLK2 0x44800000
+#define L3_44XX_BASE_CLK3 0x45000000
#define OMAP44XX_EMIF1_BASE 0x4c000000
#define OMAP44XX_EMIF2_BASE 0x4d000000
#define OMAP44XX_DMM_BASE 0x4e000000
@@ -34,6 +37,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 +49,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)
@@ -57,5 +62,7 @@
#define OMAP44XX_HSUSB_OHCI_BASE (L4_44XX_BASE + 0x64800)
#define OMAP44XX_HSUSB_EHCI_BASE (L4_44XX_BASE + 0x64C00)
+#define OMAP44XX_C2C_BASE 0x5c000000
+
#endif /* __ASM_ARCH_OMAP44XX_H */
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349f..70d31d0 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -107,7 +107,7 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od);
int omap_device_align_pm_lat(struct platform_device *pdev,
u32 new_wakeup_lat_limit);
struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
/* Other */
diff --git a/arch/arm/plat-omap/include/plat/omap_hsi.h b/arch/arm/plat-omap/include/plat/omap_hsi.h
new file mode 100644
index 0000000..1a75ed4
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/omap_hsi.h
@@ -0,0 +1,494 @@
+/*
+ * /mach/omap_hsi.h
+ *
+ * Hardware definitions for HSI and SSI.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Carlos Chinea <carlos.chinea@nokia.com>
+ * Author: Sebastien JAN <s-jan@ti.com>
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* NOTE: This file defines the registers address offsets for both the
+ * SSI and HSI devices. Most of the registers share the same offset between
+ * these devices.
+ * When common or HSI only, the constants are name HSI*. Else the SSI specific
+ * constants are name HSI_SSI*
+ */
+
+#ifndef __OMAP_HSI_H__
+#define __OMAP_HSI_H__
+
+/* Set the HSI Functional Clock to 96MHz.
+ * This is to ensure HSI will function even at OPP50. */
+#define HSI_DEFAULT_FCLK 96000000 /* 96 MHz */
+
+
+#define HSI_PORT_OFFSET 0x1000
+
+/*
+ * GDD base addr : 0x48059000 (SSI)
+ * GDD base addr : 0x4A059000 (HSI)
+ */
+#define HSI_GDD_OFFSET 0x1000
+#define HSI_GDD_BASE HSI_GDD_OFFSET /* 0x9000 */
+
+/*
+ * HST base addr:
+ * port 1: 0x4805a000 (SSI) - 0x4A05a000 (HSI)
+ * port 2: 0x4805b000 (SSI) - 0x4a05b000 (HSI)
+ */
+#define HSI_HST_OFFSET 0x2000
+#define HSI_HST_BASE(port) (HSI_HST_OFFSET + (((port) - 1) *\
+ (HSI_PORT_OFFSET)))
+ /*
+ * HSR base addr:
+ * port 1: 0x4805a800 (SSI) - 0x4A05a800 (HSI)
+ * port 2: 0x4805b800 (SSI) - 0x4A05b800 (HSI)
+ */
+#define HSI_HSR_OFFSET 0x2800
+#define HSI_HSR_BASE(port) (HSI_HSR_OFFSET + (((port) - 1) *\
+ (HSI_PORT_OFFSET)))
+/*
+ * HSI SYS registers
+ */
+#define HSI_SYS_REVISION_REG 0x0000
+#define HSI_SSI_REV_MASK 0x000000ff
+#define HSI_SSI_REV_MAJOR 0xf0
+#define HSI_SSI_REV_MINOR 0x0f
+
+#define HSI_SYS_SYSCONFIG_REG 0x0010
+#define HSI_AUTOIDLE (1 << 0)
+#define HSI_SOFTRESET (1 << 1)
+#define HSI_FREE_EMU (1 << 2) /* Only for HSI */
+#define HSI_SIDLEMODE_FORCE 0
+#define HSI_SIDLEMODE_NO (1 << 3)
+#define HSI_SIDLEMODE_SMART (1 << 4)
+#define HSI_SIDLEMODE_SMART_WAKEUP (3 << 3)
+#define HSI_SIDLEMODE_MASK 0x00000018
+#define HSI_MIDLEMODE_FORCE 0
+#define HSI_MIDLEMODE_NO (1 << 12)
+#define HSI_MIDLEMODE_SMART (1 << 13)
+#define HSI_MIDLEMODE_SMART_WAKEUP (3 << 12)
+#define HSI_MIDLEMODE_MASK 0x00003000
+
+#define HSI_SYS_SYSSTATUS_REG 0x0014
+#define HSI_RESETDONE 1
+
+#define HSI_SYS_MPU_STATUS_BASE 0x0808
+#define HSI_SYS_MPU_STATUS_PORT_OFFSET 0x10
+#define HSI_SYS_MPU_STATUS_IRQ_OFFSET 8
+
+#define HSI_SYS_MPU_STATUS_REG(port, irq) \
+ (HSI_SYS_MPU_STATUS_BASE + \
+ ((((port) - 1) * HSI_SYS_MPU_STATUS_PORT_OFFSET) +\
+ ((irq) * HSI_SYS_MPU_STATUS_IRQ_OFFSET)))
+#define HSI_SYS_MPU_ENABLE_BASE 0x080c
+#define HSI_SYS_MPU_ENABLE_PORT_OFFSET 0x10
+#define HSI_SYS_MPU_ENABLE_IRQ_OFFSET 8
+
+#define HSI_SYS_MPU_ENABLE_REG(port, irq) \
+ (HSI_SYS_MPU_ENABLE_BASE + \
+ ((((port) - 1) * HSI_SYS_MPU_ENABLE_PORT_OFFSET) +\
+ ((irq) * HSI_SYS_MPU_ENABLE_IRQ_OFFSET)))
+#define HSI_HST_DATAACCEPT(channel) (((channel) < 8) ? \
+ (1 << (channel)) : \
+ (1 << ((channel) - 8)))
+#define HSI_HSR_DATAAVAILABLE(channel) ((channel) < 8 ? \
+ (1 << ((channel) + 8)) : \
+ (1 << ((channel) - 8 + 8)))
+#define HSI_HSR_DATAOVERRUN(channel) ((channel) < 8 ? \
+ (1 << ((channel) + 16)) : \
+ (1 << ((channel) - 8 + 16)))
+
+#define HSI_ERROROCCURED (1 << 24)
+#define HSI_BREAKDETECTED (1 << 25)
+#define HSI_CAWAKEDETECTED (1 << 26)
+
+#define HSI_SYS_GDD_MPU_IRQ_STATUS_REG 0x0800
+#define HSI_SYS_GDD_MPU_IRQ_ENABLE_REG 0x0804
+#define HSI_GDD_LCH(channel) (1 << (channel))
+
+
+#define HSI_SYS_WAKE_OFFSET 0x10
+#define HSI_SYS_WAKE_BASE 0x0c00
+#define HSI_SYS_WAKE_REG(port) (HSI_SYS_WAKE_BASE +\
+ (((port) - 1) * HSI_SYS_WAKE_OFFSET))
+
+#define HSI_SYS_CLEAR_WAKE_BASE 0x0c04
+#define HSI_SYS_CLEAR_WAKE_REG(port) (HSI_SYS_CLEAR_WAKE_BASE +\
+ (((port) - 1) * HSI_SYS_WAKE_OFFSET))
+
+#define HSI_SYS_SET_WAKE_BASE 0x0c08
+#define HSI_SYS_SET_WAKE_REG(port) (HSI_SYS_SET_WAKE_BASE +\
+ (((port) - 1) * HSI_SYS_WAKE_OFFSET))
+
+#define HSI_SSI_WAKE_MASK 0xff /* for SSI */
+#define HSI_WAKE_MASK 0xffff /* for HSI */
+#define HSI_SET_WAKE_4_WIRES (0 << 16)
+#define HSI_SET_WAKE_READY_LVL_0 (0 << 17)
+#define HSI_SET_WAKE(channel) (1 << (channel) |\
+ HSI_SET_WAKE_4_WIRES |\
+ HSI_SET_WAKE_READY_LVL_0)
+#define HSI_CLEAR_WAKE(channel) (1 << (channel))
+#define HSI_WAKE(channel) (1 << (channel))
+
+#define HSI_SYS_HWINFO_REG 0x0004 /* only for HSI */
+
+/* Additional registers definitions (for channels 8 .. 15) for HSI */
+#define HSI_SYS_MPU_U_STATUS_BASE 0x0408
+#define HSI_SYS_MPU_U_STATUS_REG(port, irq) \
+ (HSI_SYS_MPU_U_STATUS_BASE + \
+ ((((port) - 1) * HSI_SYS_MPU_STATUS_PORT_OFFSET) +\
+ ((irq) * HSI_SYS_MPU_STATUS_IRQ_OFFSET)))
+
+#define HSI_SYS_MPU_U_ENABLE_BASE 0x040c
+#define HSI_SYS_MPU_U_ENABLE_REG(port, irq) \
+ (HSI_SYS_MPU_U_ENABLE_BASE + \
+ ((((port) - 1) * HSI_SYS_MPU_ENABLE_PORT_OFFSET) +\
+ ((irq) * HSI_SYS_MPU_ENABLE_IRQ_OFFSET)))
+
+/*
+ * HSI HST registers
+ */
+#define HSI_HST_ID_REG(port) (HSI_HST_BASE(port) + 0x0000)
+
+#define HSI_HST_MODE_REG(port) (HSI_HST_BASE(port) + 0x0004)
+#define HSI_MODE_VAL_MASK 3
+#define HSI_MODE_SLEEP 0
+#define HSI_MODE_STREAM 1
+#define HSI_MODE_FRAME 2
+#define HSI_SSI_MODE_MULTIPOINTS 3 /* SSI only */
+#define HSI_FLOW_OFFSET 2 /* HSI only */
+#define HSI_FLOW_VAL_MASK 3 /* HSI only */
+#define HSI_FLOW_SYNCHRONIZED 0 /* HSI only */
+#define HSI_FLOW_PIPELINED 1 /* HSI only */
+#define HSI_FLOW_REAL_TIME 2 /* HSI only */
+#define HSI_HST_MODE_WAKE_CTRL_AUTO (1 << 4) /* HSI only */
+#define HSI_HST_MODE_WAKE_CTRL_SW (0 << 4) /* HSI only */
+
+#define HSI_HST_FRAMESIZE_REG(port) (HSI_HST_BASE(port) + 0x0008)
+#define HSI_FRAMESIZE_DEFAULT 31
+#define HSI_FRAMESIZE_MAX 0x1f
+
+#define HSI_HST_TXSTATE_REG(port) (HSI_HST_BASE(port) + 0x000c)
+#define HSI_HST_TXSTATE_VAL_MASK 0x07
+#define HSI_HST_TXSTATE_IDLE 0
+
+#define HSI_HST_BUFSTATE_REG(port) (HSI_HST_BASE(port) + 0x0010)
+#define HSI_HST_BUFSTATE_FIFO_REG(fifo) (((fifo) < 8) ? \
+ HSI_HST_BUFSTATE_REG(1) : \
+ HSI_HST_BUFSTATE_REG(2))
+#define HSI_BUFSTATE_CHANNEL(channel) ((channel) < 8 ? \
+ (1 << (channel)) : \
+ (1 << ((channel) - 8)))
+
+#define HSI_HST_DIVISOR_REG(port) (HSI_HST_BASE(port) + 0x0018)
+#define HSI_DIVISOR_DEFAULT 1
+#define HSI_SSI_MAX_TX_DIVISOR 0x7f /* for SSI */
+#define HSI_MAX_TX_DIVISOR 0xff /* for HSI */
+
+#define HSI_HST_BREAK_REG(port) (HSI_HST_BASE(port) + 0x0020)
+#define HSI_HST_CHANNELS_REG(port) (HSI_HST_BASE(port) + 0x0024)
+#define HSI_CHANNELS_DEFAULT 4
+#define HSI_SSI_CHANNELS_MAX 8 /* for SSI */
+#define HSI_CHANNELS_MAX 16 /* for HSI */
+
+#define HSI_HST_ARBMODE_REG(port) (HSI_HST_BASE(port) + 0x0028)
+#define HSI_ARBMODE_ROUNDROBIN 0
+#define HSI_ARBMODE_PRIORITY 1
+
+#define HSI_HST_BUFFER_BASE(port) (HSI_HST_BASE(port) + 0x0080)
+#define HSI_HST_BUFFER_CH_REG(port, channel) (HSI_HST_BUFFER_BASE(port) +\
+ ((channel) * 4))
+#define HSI_HST_BUFFER_FIFO_REG(fifo) (((fifo) < 8) ? \
+ (HSI_HST_BUFFER_CH_REG(1, (fifo))) : \
+ (HSI_HST_BUFFER_CH_REG(2, (fifo) - 8)))
+
+#define HSI_HST_SWAPBUF_BASE(port) (HSI_HST_BASE(port) + 0x00c0)
+#define HSI_HST_SWAPBUF_CH_REG(port, channel) (HSI_HST_SWAPBUF_BASE(port) +\
+ ((channel) * 4))
+
+
+/* Additional registers for HSI */
+#define HSI_HST_FIFO_COUNT 16
+#define HSI_HST_FIFO_SIZE 8
+#define HSI_HST_MAPPING_FIFO_REG(fifo) (HSI_HST_BASE(1) + 0x0100 +\
+ ((fifo) * 4))
+#define HSI_MAPPING_ENABLE 1
+#define HSI_MAPPING_CH_NUMBER_OFFSET 1
+#define HSI_MAPPING_PORT_NUMBER_OFFSET 7
+#define HSI_HST_MAPPING_THRESH_OFFSET 10
+#define HSI_HST_MAPPING_THRESH_VALUE (0x0 << HSI_HST_MAPPING_THRESH_OFFSET)
+
+/*
+ * HSI HSR registers
+ */
+#define HSI_HSR_ID_REG(port) (HSI_HSR_BASE(port) + 0x0000)
+
+#define HSI_HSR_MODE_REG(port) (HSI_HSR_BASE(port) + 0x0004)
+
+#define HSI_HSR_MODE_MODE_VAL_MASK (3 << 0) /* HSI only */
+#define HSI_HSR_MODE_FLOW_VAL_MASK (3 << 2) /* HSI only */
+#define HSI_HSR_MODE_WAKE_STATUS (1 << 4) /* HSI only */
+#define HSI_HSR_MODE_MODE_VAL_SLEEP 0xFFFFFFFC /* HSI only */
+
+#define HSI_HSR_FRAMESIZE_REG(port) (HSI_HSR_BASE(port) + 0x0008)
+
+#define HSI_HSR_RXSTATE_REG(port) (HSI_HSR_BASE(port) + 0x000c)
+
+#define HSI_HSR_BUFSTATE_REG(port) (HSI_HSR_BASE(port) + 0x0010)
+#define HSI_HSR_BUFSTATE_FIFO_REG(fifo) (((fifo) < 8) ? \
+ HSI_HSR_BUFSTATE_REG(1) : \
+ HSI_HSR_BUFSTATE_REG(2))
+
+#define HSI_HSR_BREAK_REG(port) (HSI_HSR_BASE(port) + 0x001c)
+
+#define HSI_HSR_ERROR_REG(port) (HSI_HSR_BASE(port) + 0x0020)
+#define HSI_HSR_ERROR_SIG 1
+#define HSI_HSR_ERROR_FTE (1 << 1) /* HSI only */
+#define HSI_HSR_ERROR_TBE (1 << 4) /* HSI only */
+#define HSI_HSR_ERROR_RME (1 << 7) /* HSI only */
+#define HSI_HSR_ERROR_TME (1 << 11) /* HSI only */
+
+#define HSI_HSR_ERRORACK_REG(port) (HSI_HSR_BASE(port) + 0x0024)
+
+#define HSI_HSR_CHANNELS_REG(port) (HSI_HSR_BASE(port) + 0x0028)
+
+#define HSI_HSR_OVERRUN_REG(port) (HSI_HSR_BASE(port) + 0x002c)
+
+#define HSI_HSR_OVERRUNACK_REG(port) (HSI_HSR_BASE(port) + 0x0030)
+
+#define HSI_HSR_COUNTERS_REG(port) (HSI_HSR_BASE(port) + 0x0034)
+#define SSI_TIMEOUT_REG(port) (HSI_HSR_COUNTERS_REG(port))
+#define HSI_TIMEOUT_DEFAULT 0 /* SSI only */
+#define HSI_SSI_RX_TIMEOUT_OFFSET 0 /* SSI only */
+#define HSI_SSI_RX_TIMEOUT_MASK 0x1ff /* SSI only */
+#define HSI_COUNTERS_FT_MASK 0x000fffff /* HSI only */
+#define HSI_COUNTERS_TB_MASK 0x00f00000 /* HSI only */
+#define HSI_COUNTERS_FB_MASK 0xff000000 /* HSI only */
+#define HSI_COUNTERS_FT_OFFSET 0 /* HSI only */
+#define HSI_COUNTERS_TB_OFFSET 20 /* HSI only */
+#define HSI_COUNTERS_FB_OFFSET 24 /* HSI only */
+/* Default FT value: 2 x max_bits_per_frame + 20% margin */
+#define HSI_COUNTERS_FT_DEFAULT (90 << HSI_COUNTERS_FT_OFFSET)
+#define HSI_COUNTERS_TB_DEFAULT (6 << HSI_COUNTERS_TB_OFFSET)
+#define HSI_COUNTERS_FB_DEFAULT (8 << HSI_COUNTERS_FB_OFFSET)
+#define HSI_HSR_COMBINE_COUNTERS(FB, TB, FT) \
+ (((FB << HSI_COUNTERS_FB_OFFSET) & HSI_COUNTERS_FB_MASK) \
+ ((TB << HSI_COUNTERS_TB_OFFSET) & HSI_COUNTERS_TB_MASK) \
+ ((FT << HSI_COUNTERS_FT_OFFSET) & HSI_COUNTERS_FT_MASK))
+#define SSI_SSR_COMBINE_COUNTERS(FT) \
+ ((FT << HSI_SSI_RX_TIMEOUT_OFFSET) & HSI_SSI_RX_TIMEOUT_MASK)
+
+#define HSI_HSR_BUFFER_BASE(port) (HSI_HSR_BASE(port) + 0x0080)
+#define HSI_HSR_BUFFER_CH_REG(port, channel) (HSI_HSR_BUFFER_BASE(port) +\
+ ((channel) * 4))
+#define HSI_HSR_BUFFER_FIFO_REG(fifo) (((fifo) < 8) ? \
+ (HSI_HSR_BUFFER_CH_REG(1, (fifo))) : \
+ (HSI_HSR_BUFFER_CH_REG(2, (fifo) - 8)))
+
+#define HSI_HSR_SWAPBUF_BASE(port) (HSI_HSR_BASE(port) + 0x00c0)
+#define HSI_HSR_SWAPBUF_CH_REG(port, channel) (HSI_HSR_SWAPBUF_BASE(port) +\
+ ((channel) * 4))
+
+/* Additional registers for HSI */
+#define HSI_HSR_FIFO_COUNT 16
+#define HSI_HSR_FIFO_SIZE 8
+#define HSI_HSR_MAPPING_FIFO_REG(fifo) (HSI_HSR_BASE(1) + 0x0100 +\
+ ((fifo) * 4))
+#define HSI_HSR_MAPPING_WORDS_MASK (0xf << 10)
+
+#define HSI_HSR_DLL_REG (HSI_HSR_BASE(1) + 0x0144)
+#define HSI_HSR_DLL_COCHRE 1
+#define HSI_HSR_DLL_COCHGR (1 << 4)
+#define HSI_HSR_DLL_INCO_MASK 0x0003ff00
+#define HSI_HSR_DLL_INCO_OFFSET 8
+
+#define HSI_HSR_DIVISOR_REG(port) (HSI_HSR_BASE(port) + 0x014C)
+#define HSI_HSR_DIVISOR_MASK 0xff
+#define HSI_MAX_RX_DIVISOR 0xff
+
+/*
+ * HSI GDD registers
+ */
+#define HSI_SSI_DMA_CHANNEL_MAX 8
+#define HSI_HSI_DMA_CHANNEL_MAX 16
+
+#define HSI_SSI_GDD_HW_ID_REG (HSI_GDD_BASE + 0x0000)
+
+#define HSI_SSI_GDD_PPORT_ID_REG (HSI_GDD_BASE + 0x0010)
+
+#define HSI_SSI_GDD_MPORT_ID_REG (HSI_GDD_BASE + 0x0014)
+
+#define HSI_SSI_GDD_PPORT_SR_REG (HSI_GDD_BASE + 0x0020)
+#define HSI_PPORT_ACTIVE_LCH_NUMBER_MASK 0xff
+
+#define HSI_GDD_MPORT_SR_REG (HSI_GDD_BASE + 0x0024)
+#define HSI_SSI_MPORT_ACTIVE_LCH_NUMBER_MASK 0xff
+
+#define HSI_SSI_GDD_TEST_REG (HSI_GDD_BASE + 0x0040)
+#define HSI_SSI_TEST 1
+
+#define HSI_GDD_GCR_REG (HSI_GDD_BASE + 0x0100)
+#define HSI_CLK_AUTOGATING_ON (1 << 3)
+#define HSI_SWITCH_OFF (1 << 0)
+
+#define HSI_GDD_GRST_REG (HSI_GDD_BASE + 0x0200)
+#define HSI_GDD_GRST_SWRESET 1
+
+#define HSI_GDD_CSDP_BASE (HSI_GDD_BASE + 0x0800)
+#define HSI_GDD_CSDP_OFFSET 0x40
+#define HSI_GDD_CSDP_REG(channel) (HSI_GDD_CSDP_BASE +\
+ ((channel) * HSI_GDD_CSDP_OFFSET))
+
+#define HSI_DST_BURST_EN_MASK 0xc000
+#define HSI_DST_SINGLE_ACCESS0 0
+#define HSI_DST_SINGLE_ACCESS (1 << 14)
+#define HSI_DST_BURST_4X32_BIT (2 << 14)
+#define HSI_DST_BURST_8x32_BIT (3 << 14)
+
+#define HSI_DST_MASK 0x1e00
+#define HSI_DST_MEMORY_PORT (8 << 9)
+#define HSI_DST_PERIPHERAL_PORT (9 << 9)
+
+#define HSI_SRC_BURST_EN_MASK 0x0180
+#define HSI_SRC_SINGLE_ACCESS0 0
+#define HSI_SRC_SINGLE_ACCESS (1 << 7)
+#define HSI_SRC_BURST_4x32_BIT (2 << 7)
+#define HSI_SRC_BURST_8x32_BIT (3 << 7)
+
+#define HSI_SRC_MASK 0x003c
+#define HSI_SRC_MEMORY_PORT (8 << 2)
+#define HSI_SRC_PERIPHERAL_PORT (9 << 2)
+
+#define HSI_DATA_TYPE_MASK 3
+#define HSI_DATA_TYPE_S32 2
+
+#define HSI_GDD_CCR_BASE (HSI_GDD_BASE + 0x0802)
+#define HSI_GDD_CCR_OFFSET 0x40
+#define HSI_GDD_CCR_REG(channel) (HSI_GDD_CCR_BASE +\
+ ((channel) * HSI_GDD_CCR_OFFSET))
+#define HSI_DST_AMODE_MASK (3 << 14)
+#define HSI_DST_AMODE_CONST 0
+#define HSI_DST_AMODE_POSTINC (1 << 14)
+
+#define HSI_SRC_AMODE_MASK (3 << 12)
+#define HSI_SRC_AMODE_CONST 0
+#define HSI_SRC_AMODE_POSTINC (1 << 12)
+
+#define HSI_CCR_ENABLE (1 << 7)
+
+#define HSI_CCR_SYNC_MASK 0x001f /* only for SSI */
+
+#define HSI_GDD_CCIR_BASE (HSI_GDD_BASE + 0x0804)
+#define HSI_GDD_CCIR_OFFSET 0x40
+#define HSI_GDD_CCIR_REG(channel) (HSI_GDD_CCIR_BASE +\
+ ((channel) * HSI_GDD_CCIR_OFFSET))
+
+#define HSI_BLOCK_IE (1 << 5)
+#define HSI_HALF_IE (1 << 2)
+#define HSI_TOUT_IE (1 << 0)
+
+#define HSI_GDD_CSR_BASE (HSI_GDD_BASE + 0x0806)
+#define HSI_GDD_CSR_OFFSET 0x40
+#define HSI_GDD_CSR_REG(channel) (HSI_GDD_CSR_BASE +\
+ ((channel) * HSI_GDD_CSR_OFFSET))
+
+#define HSI_CSR_SYNC (1 << 6)
+#define HSI_CSR_BLOCK (1 << 5) /* Full block is transferred */
+#define HSI_CSR_HALF (1 << 2) /* Half block is transferred */
+#define HSI_CSR_TOUT (1 << 0) /* Time-out overflow occurs */
+
+#define HSI_GDD_CSSA_BASE (HSI_GDD_BASE + 0x0808)
+#define HSI_GDD_CSSA_OFFSET 0x40
+#define HSI_GDD_CSSA_REG(channel) (HSI_GDD_CSSA_BASE +\
+ ((channel) * HSI_GDD_CSSA_OFFSET))
+
+
+#define HSI_GDD_CDSA_BASE (HSI_GDD_BASE + 0x080c)
+#define HSI_GDD_CDSA_OFFSET 0x40
+#define HSI_GDD_CDSA_REG(channel) (HSI_GDD_CDSA_BASE +\
+ ((channel) * HSI_GDD_CDSA_OFFSET))
+
+#define HSI_GDD_CEN_BASE (HSI_GDD_BASE + 0x0810)
+#define HSI_GDD_CEN_OFFSET 0x40
+#define HSI_GDD_CEN_REG(channel) (HSI_GDD_CEN_BASE +\
+ ((channel) * HSI_GDD_CEN_OFFSET))
+
+
+#define HSI_GDD_CSAC_BASE (HSI_GDD_BASE + 0x0818)
+#define HSI_GDD_CSAC_OFFSET 0x40
+#define HSI_GDD_CSAC_REG(channel) (HSI_GDD_CSAC_BASE +\
+ ((channel) * HSI_GDD_CSAC_OFFSET))
+
+#define HSI_GDD_CDAC_BASE (HSI_GDD_BASE + 0x081a)
+#define HSI_GDD_CDAC_OFFSET 0x40
+#define HSI_GDD_CDAC_REG(channel) (HSI_GDD_CDAC_BASE +\
+ ((channel) * HSI_GDD_CDAC_OFFSET))
+
+#define HSI_SSI_GDD_CLNK_CTRL_BASE (HSI_GDD_BASE + 0x0828)
+#define HSI_SSI_GDD_CLNK_CTRL_OFFSET 0x40
+#define HSI_SSI_GDD_CLNK_CTRL_REG(channel) (HSI_SSI_GDD_CLNK_CTRL_BASE +\
+ (channel * HSI_SSI_GDD_CLNK_CTRL_OFFSET))
+
+#define HSI_SSI_ENABLE_LNK (1 << 15)
+#define HSI_SSI_STOP_LNK (1 << 14)
+#define HSI_SSI_NEXT_CH_ID_MASK 0xf
+
+/*
+ * HSI Helpers
+ */
+#define HSI_SYS_MPU_ENABLE_CH_REG(port, irq, channel) \
+ (((channel) < HSI_SSI_CHANNELS_MAX) ? \
+ HSI_SYS_MPU_ENABLE_REG(port, irq) : \
+ HSI_SYS_MPU_U_ENABLE_REG(port, irq))
+
+#define HSI_SYS_MPU_STATUS_CH_REG(port, irq, channel) \
+ ((channel < HSI_SSI_CHANNELS_MAX) ? \
+ HSI_SYS_MPU_STATUS_REG(port, irq) : \
+ HSI_SYS_MPU_U_STATUS_REG(port, irq))
+/**
+ * struct omap_ssi_config - SSI board configuration
+ * @num_ports: Number of ports in use
+ * @cawake_line: Array of cawake gpio lines
+ */
+struct omap_ssi_board_config {
+ unsigned int num_ports;
+ int cawake_gpio[2];
+};
+extern int omap_ssi_config(struct omap_ssi_board_config *ssi_config);
+
+/**
+ * struct omap_hsi_config - HSI board configuration
+ * @num_ports: Number of ports in use
+ */
+struct omap_hsi_board_config {
+ unsigned int num_ports;
+};
+extern int omap_hsi_config(struct omap_hsi_board_config *hsi_config);
+
+#ifdef CONFIG_OMAP_HSI
+extern int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup);
+extern int omap_hsi_prepare_idle(void);
+extern int omap_hsi_wakeup(int hsi_port);
+extern int omap_hsi_is_io_wakeup_from_hsi(void);
+#else
+inline int omap_hsi_prepare_suspend(int hsi_port,
+ bool dev_may_wakeup) { return -ENOSYS; }
+inline int omap_hsi_prepare_idle(void) { return -ENOSYS; }
+inline int omap_hsi_wakeup(int hsi_port) { return -ENOSYS; }
+inline int omap_hsi_is_io_wakeup_from_hsi(void) { return -ENOSYS; }
+
+#endif
+
+#endif /* __OMAP_HSI_H__ */
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c..2f279ad 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -40,6 +40,7 @@ struct omap_device;
extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1;
extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
+extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3;
/*
* OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant
@@ -69,6 +70,13 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
#define SYSC_TYPE2_MIDLEMODE_SHIFT 4
#define SYSC_TYPE2_MIDLEMODE_MASK (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT)
+/*
+ * OCP SYSCONFIG bit shifts/masks TYPE3. These are for IPs compliant
+ * that only implement the sidle feature.
+ */
+#define SYSC_TYPE3_SIDLEMODE_SHIFT 0
+#define SYSC_TYPE3_SIDLEMODE_MASK (0x3 << SYSC_TYPE3_SIDLEMODE_SHIFT)
+
/* OCP SYSSTATUS bit shifts/masks */
#define SYSS_RESETDONE_SHIFT 0
#define SYSS_RESETDONE_MASK (1 << SYSS_RESETDONE_SHIFT)
@@ -77,7 +85,6 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
#define HWMOD_IDLEMODE_FORCE (1 << 0)
#define HWMOD_IDLEMODE_NO (1 << 1)
#define HWMOD_IDLEMODE_SMART (1 << 2)
-/* Slave idle mode flag only */
#define HWMOD_IDLEMODE_SMART_WKUP (1 << 3)
/**
@@ -258,6 +265,7 @@ struct omap_hwmod_ocp_if {
#define MSTANDBY_FORCE (HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
#define MSTANDBY_NO (HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
#define MSTANDBY_SMART (HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
+#define MSTANDBY_SMART_WKUP (HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT)
/* omap_hwmod_sysconfig.sysc_flags capability flags */
#define SYSC_HAS_AUTOIDLE (1 << 0)
@@ -300,6 +308,7 @@ struct omap_hwmod_sysc_fields {
* @rev_offs: IP block revision register offset (from module base addr)
* @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
* @syss_offs: OCP_SYSSTATUS register offset (from module base addr)
+ * @srst_udelay: Delay needed after doing a softreset in usecs
* @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART}
* @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported
* @clockact: the default value of the module CLOCKACTIVITY bits
@@ -325,6 +334,7 @@ struct omap_hwmod_class_sysconfig {
u16 sysc_offs;
u16 syss_offs;
u16 sysc_flags;
+ u16 srst_udelay;
u8 idlemodes;
u8 clockact;
struct omap_hwmod_sysc_fields *sysc_fields;
@@ -359,11 +369,15 @@ struct omap_hwmod_omap2_prcm {
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
* @clkctrl_reg: PRCM address of the clock control register
* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @context_reg: addres of the context register
+ * @ctx_restore_trig : indicates if RFF or DFF or both lost
+ * should trigger ctx restore.
* @submodule_wkdep_bit: bit shift of the WKDEP range
*/
struct omap_hwmod_omap4_prcm {
void __iomem *clkctrl_reg;
void __iomem *rstctrl_reg;
+ void __iomem *context_reg;
u8 submodule_wkdep_bit;
};
@@ -519,8 +533,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;
@@ -598,10 +610,14 @@ int omap_hwmod_for_each_by_class(const char *classname,
void *user);
int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
+
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh);
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh);
/*
* Chip variant-specific hwmod init routines - XXX should be converted
* to use initcalls once the initial boot ordering is straightened out
@@ -611,4 +627,6 @@ extern int omap2430_hwmod_init(void);
extern int omap3xxx_hwmod_init(void);
extern int omap44xx_hwmod_init(void);
+extern struct device *omap_hwmod_name_get_dev(const char *oh_name);
+
#endif
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..3de2a38
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/remoteproc.h
@@ -0,0 +1,151 @@
+/*
+ * 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>
+#include <plat/omap_device.h>
+
+/*
+ * struct omap_rproc_timers_info - optional timers for the omap rproc
+ *
+ * @id: timer id to use by the remoteproc
+ * @odt: timer pointer
+ */
+struct omap_rproc_timers_info {
+ int id;
+ struct omap_dm_timer *odt;
+};
+
+/*
+ * 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
+ * @clkdm_name: name of clock domain in which this device is located
+ * @clkdm: clock domain in which this device is located
+ * @ops: platform-specific start/stop rproc handlers
+ * @memory_maps: table of da-to-pa iommu memory maps
+ * @memory_pool: platform-specific pool data
+ * @omap_rproc_timers_info: optional, timer(s) rproc can use
+ */
+struct omap_rproc_pdata {
+ const char *name;
+ const char *iommu_name;
+ const char *oh_name;
+ const char *oh_name_opt;
+ const char *firmware;
+ const char *clkdm_name;
+ struct clockdomain *clkdm;
+ const struct rproc_ops *ops;
+ struct rproc_mem_pool *memory_pool;
+ struct omap_rproc_timers_info *timers;
+ u32 idle_addr;
+ u32 idle_mask;
+ u32 suspend_addr;
+ u32 suspend_mask;
+ unsigned sus_timeout;
+ char *sus_mbox_name;
+ u8 timers_cnt;
+};
+
+enum omap_rproc_mempool_type {
+ OMAP_RPROC_MEMPOOL_STATIC,
+ OMAP_RPROC_MEMPOOL_DYNAMIC
+};
+
+#if defined(CONFIG_OMAP_REMOTE_PROC)
+void omap_ipu_reserve_sdram_memblock(void);
+u32 omap_ipu_get_mempool_size(enum omap_rproc_mempool_type type);
+phys_addr_t omap_ipu_get_mempool_base(enum omap_rproc_mempool_type type);
+void omap_ipu_set_static_mempool(u32 start, u32 size);
+#else
+static inline void omap_ipu_reserve_sdram_memblock(void) { }
+static inline u32 omap_ipu_get_mempool_size(enum omap_rproc_mempool_type type)
+{
+ return 0;
+}
+static inline phys_addr_t omap_ipu_get_mempool_base(
+ enum omap_rproc_mempool_type type)
+{
+ return 0;
+}
+static inline void omap_ipu_set_static_mempool(u32 start, u32 size) { }
+#endif
+
+int omap_rproc_deactivate(struct omap_device *od);
+int omap_rproc_activate(struct omap_device *od);
+#define OMAP_RPROC_DEFAULT_PM_LATENCY \
+ .deactivate_func = omap_rproc_deactivate, \
+ .activate_func = omap_rproc_activate, \
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
+
+struct exc_regs {
+ u32 r0;
+ u32 r1;
+ u32 r2;
+ u32 r3;
+ u32 r4;
+ u32 r5;
+ u32 r6;
+ u32 r7;
+ u32 r8;
+ u32 r9;
+ u32 r10;
+ u32 r11;
+ u32 r12;
+ u32 sp;
+ u32 lr;
+ u32 pc;
+ u32 psr;
+ u32 ICSR; /* NVIC registers */
+ u32 MMFSR;
+ u32 BFSR;
+ u32 UFSR;
+ u32 HFSR;
+ u32 DFSR;
+ u32 MMAR;
+ u32 BFAR;
+ u32 AFSR;
+};
+
+static inline void remoteproc_fill_pt_regs(struct pt_regs *regs,
+ struct exc_regs *xregs)
+{
+ regs->ARM_r0 = xregs->r0;
+ regs->ARM_ORIG_r0 = xregs->r0;
+ regs->ARM_r1 = xregs->r1;
+ regs->ARM_r2 = xregs->r2;
+ regs->ARM_r3 = xregs->r3;
+ regs->ARM_r4 = xregs->r4;
+ regs->ARM_r5 = xregs->r5;
+ regs->ARM_r6 = xregs->r6;
+ regs->ARM_r7 = xregs->r7;
+ regs->ARM_r8 = xregs->r8;
+ regs->ARM_r9 = xregs->r9;
+ regs->ARM_r10 = xregs->r10;
+ regs->ARM_fp = xregs->r11;
+ regs->ARM_ip = xregs->r12;
+ regs->ARM_sp = xregs->sp;
+ regs->ARM_lr = xregs->lr;
+ regs->ARM_pc = xregs->pc;
+ regs->ARM_cpsr = xregs->psr;
+}
+
+#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..0dfb781
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/rpres.h
@@ -0,0 +1,57 @@
+/*
+ * 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_constraint {
+ RPRES_CONSTRAINT_SCALE,
+ RPRES_CONSTRAINT_LATENCY,
+ RPRES_CONSTRAINT_BANDWIDTH,
+};
+
+enum {
+ RPRES_INACTIVE,
+ RPRES_ACTIVE,
+};
+
+struct rpres_ops {
+ int (*start)(struct platform_device *pdev);
+ int (*stop)(struct platform_device *pdev);
+ int (*set_lat)(struct platform_device *pdev, long v);
+ int (*set_bw)(struct platform_device *pdev, long v);
+ int (*scale_dev)(struct platform_device *pdev, long v);
+};
+
+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 device *(*get_dev)(void);
+};
+
+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 *);
+int rpres_set_constraints(struct rpres *, enum rpres_constraint type, long val);
+#endif /* _PLAT_OMAP_RPRES_H */
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 2723f91..8e41fb6 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -103,15 +103,23 @@
#ifndef __ASSEMBLER__
struct omap_board_data;
+struct omap_uart_port_info;
+struct omap_device_pad;
extern void omap_serial_init(void);
-extern void omap_serial_init_port(struct omap_board_data *bdata);
-extern int omap_uart_can_sleep(void);
-extern void omap_uart_check_wakeup(void);
-extern void omap_uart_prepare_suspend(void);
-extern void omap_uart_prepare_idle(int num);
-extern void omap_uart_resume_idle(int num);
-extern void omap_uart_enable_irqs(int enable);
+extern void omap_serial_board_init(struct omap_uart_port_info *platform_data);
+extern void omap_serial_init_port(struct omap_board_data *bdata,
+ struct omap_uart_port_info *platform_data);
+void __init omap_serial_init_port_pads(int id, struct omap_device_pad *pads,
+ int size, struct omap_uart_port_info *info);
+extern u32 omap_uart_resume_idle(void);
+extern int omap_uart_wake(u8 id);
+extern int omap_uart_enable(u8 uart_num);
+extern int omap_uart_disable(u8 uart_num);
+
+#define MUX_PULL_UP ((1<<8) | (1<<4) | (1<<3) | (7))
+void omap_rts_mux_write(u16 val, int num);
+
#endif
#endif
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index f500fc3..a6000d4 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -15,6 +15,7 @@
#include <asm/fncpy.h>
extern void *omap_sram_push_address(unsigned long size);
+extern unsigned long omap_get_sram_barrier_base(void);
/* Macro to push a function to the internal SRAM, using the fncpy API */
#define omap_sram_push(funcp, size) ({ \
diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
new file mode 100644
index 0000000..5f0d6b3
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
@@ -0,0 +1,65 @@
+/*
+ * OMAP446x Temperature sensor header file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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.
+ *
+ * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
+
+/*
+ * Offsets from the base of temperature sensor registers
+ */
+#define TEMP_SENSOR_CTRL_OFFSET 0x00
+#define BGAP_CTRL_OFFSET 0x4c
+#define BGAP_COUNTER_OFFSET 0x50
+#define BGAP_THRESHOLD_OFFSET 0x54
+#define BGAP_TSHUT_OFFSET 0x58
+#define BGAP_STATUS_OFFSET 0x5c
+
+#define OMAP_TSHUT_GPIO 86
+
+
+/*
+ * omap_temp_sensor platform data
+ * @name - name
+ * @irq - Irq number for thermal alertemp_sensor
+ * @offset - offset of the temp sensor ctrl register
+ */
+struct omap_temp_sensor_pdata {
+ char *name;
+ u32 offset;
+ int irq;
+};
+
+#ifdef CONFIG_OMAP_TEMP_SENSOR
+void omap_temp_sensor_resume_idle(void);
+void omap_temp_sensor_prepare_idle(void);
+#else
+static inline void omap_temp_sensor_resume_idle(void) { }
+static inline void omap_temp_sensor_prepare_idle(void) { }
+#endif
+
+#ifdef CONFIG_OMAP_DIE_TEMP_SENSOR
+void omap_temp_sensor_idle(int idle_state);
+#else
+static inline void omap_temp_sensor_idle(int idle_state) { }
+#endif
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 17d3c93..3be4a83 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -41,6 +41,11 @@ struct usbhs_omap_board_data {
* Each PHY can have a separate regulator.
*/
struct regulator *regulator[OMAP3_HS_USB_PORTS];
+ /*
+ * Each Port can have an external transceiver requiring clock control
+ * for low power mode entry
+ */
+ struct clk *transceiver_clk[OMAP3_HS_USB_PORTS];
};
struct ehci_hcd_omap_platform_data {
@@ -48,6 +53,11 @@ struct ehci_hcd_omap_platform_data {
int reset_gpio_port[OMAP3_HS_USB_PORTS];
struct regulator *regulator[OMAP3_HS_USB_PORTS];
unsigned phy_reset:1;
+ /*
+ * Each Port can have an external transceiver requiring clock control
+ * for low power mode entry
+ */
+ struct clk *transceiver_clk[OMAP3_HS_USB_PORTS];
};
struct ohci_hcd_omap_platform_data {
@@ -100,9 +110,6 @@ extern void usb_musb_init(struct omap_musb_board_data *board_data);
extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
-extern int omap_usbhs_enable(struct device *dev);
-extern void omap_usbhs_disable(struct device *dev);
-
extern int omap4430_phy_power(struct device *dev, int ID, int on);
extern int omap4430_phy_set_clk(struct device *dev, int on);
extern int omap4430_phy_init(struct device *dev);
@@ -293,4 +300,9 @@ static inline u32 omap1_usb2_init(unsigned nwires, unsigned alt_pingroup)
}
#endif
+extern void usbhs_wakeup(void);
+extern void omap4_trigger_ioctrl(void);
+
+#define USBHS_EHCI_HWMODNAME "usbhs_ehci"
+
#endif /* __ASM_ARCH_OMAP_USB_H */
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 34fc31e..632fbe2 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);
}
/*
@@ -244,11 +237,14 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
struct iotlb_lock l;
struct cr_regs *cr;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return -EBUSY;
+ }
+
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 +273,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 +286,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,7 +302,10 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
int i;
struct cr_regs cr;
- clk_enable(obj->clk);
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return;
+ }
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start;
@@ -327,7 +324,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 +358,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 +377,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 +388,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 +401,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 +410,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 +455,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 +492,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 +521,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 +538,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 +551,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 +576,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;
}
@@ -649,6 +626,11 @@ int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
{
int err;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return -EBUSY;
+ }
+
flush_iotlb_page(obj, e->da);
err = iopgtable_store_entry_core(obj, e);
#ifdef PREFETCH_IOTLB
@@ -670,6 +652,11 @@ void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
{
u32 *iopgd, *iopte = NULL;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return;
+ }
+
iopgd = iopgd_offset(obj, da);
if (!*iopgd)
goto out;
@@ -739,6 +726,11 @@ size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
{
size_t bytes;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return 0;
+ }
+
spin_lock(&obj->page_table_lock);
bytes = iopgtable_clear_entry_core(obj, da);
@@ -770,7 +762,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 +782,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;
@@ -800,7 +790,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
return IRQ_HANDLED;
- iommu_disable(obj);
+ iommu_write_reg(obj, 0, MMU_IRQENABLE);
iopgd = iopgd_offset(obj, da);
@@ -839,7 +829,7 @@ int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
{
if (!obj)
- return -EFAULT;
+ return -EIO;
if (end < start || !PAGE_ALIGN(start | end))
return -EINVAL;
@@ -871,9 +861,13 @@ struct iommu *iommu_get(const char *name)
mutex_lock(&obj->iommu_lock);
if (obj->refcount++ == 0) {
+ dev_info(obj->dev, "%s: %s qos_request\n", __func__, obj->name);
+ pm_qos_update_request(obj->qos_request, 10);
err = iommu_enable(obj);
- if (err)
+ if (err) {
+ pm_qos_update_request(obj->qos_request, -1);
goto err_enable;
+ }
flush_iotlb_all(obj);
}
@@ -906,8 +900,16 @@ void iommu_put(struct iommu *obj)
mutex_lock(&obj->iommu_lock);
- if (--obj->refcount == 0)
+ if (!obj->refcount) {
+ dev_err(obj->dev, "%s: %s unbalanced iommu_get/put\n",
+ __func__, obj->name);
+ return;
+ }
+
+ if (--obj->refcount == 0) {
iommu_disable(obj);
+ pm_qos_update_request(obj->qos_request, -1);
+ }
module_put(obj->owner);
@@ -944,6 +946,30 @@ int iommu_set_isr(const char *name,
}
EXPORT_SYMBOL_GPL(iommu_set_isr);
+int iommu_set_secure(const char *name, bool enable, void *data)
+{
+ struct device *dev;
+ struct iommu *obj;
+
+ dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
+ device_match_by_alias);
+ if (!dev)
+ return -ENODEV;
+
+ obj = to_iommu(dev);
+ mutex_lock(&obj->iommu_lock);
+ if (obj->refcount) {
+ mutex_unlock(&obj->iommu_lock);
+ return -EBUSY;
+ }
+ obj->secure_mode = enable;
+ obj->secure_ttb = data;
+ mutex_unlock(&obj->iommu_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_set_secure);
+
/*
* OMAP Device MMU(IOMMU) detection
*/
@@ -951,25 +977,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 +997,18 @@ 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;
- }
+ obj->regbase = pdata->io_base;
- res = request_mem_region(res->start, resource_size(res),
- dev_name(&pdev->dev));
- if (!res) {
- err = -EIO;
- goto err_mem;
+ obj->qos_request = kzalloc(sizeof(*obj->qos_request), GFP_KERNEL);
+ if (!obj->qos_request) {
+ kfree(obj);
+ return -ENOMEM;
}
- obj->regbase = ioremap(res->start, resource_size(res));
- if (!obj->regbase) {
- err = -ENOMEM;
- goto err_ioremap;
- }
+ pm_qos_add_request(obj->qos_request, PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
- 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 +1029,27 @@ 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);
+ pm_qos_remove_request(obj->qos_request);
+ kfree(obj->qos_request);
- 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 83a37c5..6e711b9 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -163,10 +163,10 @@ static void sgtable_free(struct sg_table *sgt)
if (!sgt)
return;
+ pr_debug("%s: sgt:%p\n", __func__, sgt);
+
sg_free_table(sgt);
kfree(sgt);
-
- pr_debug("%s: sgt:%p\n", __func__, sgt);
}
/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 69ddc9f..653153e 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -29,6 +29,7 @@
#include <linux/kfifo.h>
#include <linux/err.h>
#include <linux/notifier.h>
+#include <linux/pm_qos_params.h>
#include <plat/mailbox.h>
@@ -36,6 +37,10 @@ static struct omap_mbox **mboxes;
static int mbox_configured;
static DEFINE_MUTEX(mbox_configured_lock);
+struct pm_qos_request_list mbox_qos_request;
+
+#define SET_MPU_CORE_CONSTRAINT 10
+#define CLEAR_MPU_CORE_CONSTRAINT -1
static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
module_param(mbox_kfifo_size, uint, S_IRUGO);
@@ -251,6 +256,8 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
mutex_lock(&mbox_configured_lock);
if (!mbox_configured++) {
+ pm_qos_update_request(&mbox_qos_request,
+ SET_MPU_CORE_CONSTRAINT);
if (likely(mbox->ops->startup)) {
ret = mbox->ops->startup(mbox);
if (unlikely(ret))
@@ -260,13 +267,6 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
}
if (!mbox->use_count++) {
- ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
- mbox->name, mbox);
- if (unlikely(ret)) {
- pr_err("failed to register mailbox interrupt:%d\n",
- ret);
- goto fail_request_irq;
- }
mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
if (!mq) {
ret = -ENOMEM;
@@ -281,20 +281,29 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
}
mbox->rxq = mq;
mq->mbox = mbox;
+ ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
+ mbox->name, mbox);
+ if (unlikely(ret)) {
+ pr_err("failed to register mailbox interrupt:%d\n",
+ ret);
+ goto fail_request_irq;
+ }
}
mutex_unlock(&mbox_configured_lock);
return 0;
+fail_request_irq:
+ mbox_queue_free(mbox->rxq);
fail_alloc_rxq:
mbox_queue_free(mbox->txq);
fail_alloc_txq:
- free_irq(mbox->irq, mbox);
-fail_request_irq:
if (mbox->ops->shutdown)
mbox->ops->shutdown(mbox);
mbox->use_count--;
fail_startup:
- mbox_configured--;
+ if (!--mbox_configured)
+ pm_qos_update_request(&mbox_qos_request,
+ CLEAR_MPU_CORE_CONSTRAINT);
mutex_unlock(&mbox_configured_lock);
return ret;
}
@@ -306,14 +315,17 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
if (!--mbox->use_count) {
free_irq(mbox->irq, mbox);
tasklet_kill(&mbox->txq->tasklet);
- flush_work_sync(&mbox->rxq->work);
+ flush_work_sync(&mbox->rxq->work);
mbox_queue_free(mbox->txq);
mbox_queue_free(mbox->rxq);
}
if (likely(mbox->ops->shutdown)) {
- if (!--mbox_configured)
+ if (!--mbox_configured) {
mbox->ops->shutdown(mbox);
+ pm_qos_update_request(&mbox_qos_request,
+ CLEAR_MPU_CORE_CONSTRAINT);
+ }
}
mutex_unlock(&mbox_configured_lock);
@@ -350,7 +362,8 @@ EXPORT_SYMBOL(omap_mbox_get);
void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
{
- blocking_notifier_chain_unregister(&mbox->notifier, nb);
+ if (nb)
+ blocking_notifier_chain_unregister(&mbox->notifier, nb);
omap_mbox_fini(mbox);
}
EXPORT_SYMBOL(omap_mbox_put);
@@ -395,6 +408,7 @@ int omap_mbox_unregister(void)
for (i = 0; mboxes[i]; i++)
device_unregister(mboxes[i]->dev);
+
mboxes = NULL;
return 0;
}
@@ -413,6 +427,8 @@ static int __init omap_mbox_init(void)
mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
sizeof(mbox_msg_t));
+ pm_qos_add_request(&mbox_qos_request, PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
return 0;
}
subsys_initcall(omap_mbox_init);
@@ -420,6 +436,7 @@ subsys_initcall(omap_mbox_init);
static void __exit omap_mbox_exit(void)
{
class_unregister(&omap_mbox_class);
+ pm_qos_remove_request(&mbox_qos_request);
}
module_exit(omap_mbox_exit);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 5587acf..e02baa4 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
/*
@@ -991,6 +996,25 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
MCBSP_WRITE(mcbsp, RCCR, w);
}
+ /*Disable and Re-enable transmitter if ready */
+ if (tx && (MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) &
+ (~XRST));
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ (XRST));
+ }
+ /*Disable and Re-enable receiver if ready */
+ if (rx && (MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) &
+ (~RRST));
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) |
+ (RRST));
+ }
+
/* Dump McBSP Regs */
omap_mcbsp_dump_reg(id);
}
@@ -1522,7 +1546,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 +1637,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 +1718,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 +1775,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 +1802,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..2fdd7af
--- /dev/null
+++ b/arch/arm/plat-omap/omap-pm-helper.c
@@ -0,0 +1,345 @@
+/*
+ * 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>
+#include <linux/debugfs.h>
+#include <linux/seq_file.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 "../mach-omap2/dvfs.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;
+}
+
+#ifdef CONFIG_PM_DEBUG
+static int pm_dbg_show_tput(struct seq_file *s, void *unused)
+{
+ struct users *usr;
+
+ mutex_lock(&bus_tput->throughput_mutex);
+ list_for_each_entry(usr, &bus_tput->users_list, node)
+ seq_printf(s, "%s: %u\n", dev_name(usr->dev),
+ usr->level);
+ mutex_unlock(&bus_tput->throughput_mutex);
+
+ return 0;
+}
+
+static int pm_dbg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pm_dbg_show_tput,
+ &inode->i_private);
+}
+
+static const struct file_operations tputdebugfs_fops = {
+ .open = pm_dbg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+/**
+ * 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;
+
+#ifdef CONFIG_PM_DEBUG
+ (void) debugfs_create_file("tput", S_IRUGO,
+ NULL, (void *)bus_tput, &tputdebugfs_fops);
+#endif
+
+ 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;
+ static struct device dummy_l3_dev = {
+ .init_name = "omap_pm_set_min_bus_tput",
+ };
+ 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;
+
+ ret = omap_device_scale(&dummy_l3_dev, l3_dev, target_level);
+ if (ret)
+ pr_err("Failed: change interconnect bandwidth to %ld\n",
+ target_level);
+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..e166395
--- /dev/null
+++ b/arch/arm/plat-omap/omap-pm-interface.c
@@ -0,0 +1,251 @@
+/*
+ * 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>
+#include <linux/io.h>
+/* Interface documentation is in mach/omap-pm.h */
+#include <plat/omap-pm.h>
+#include <plat/omap_device.h>
+
+#include "omap-pm-helper.h"
+#include "../mach-omap2/prm44xx.h"
+
+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;
+}
+
+bool omap_pm_was_context_lost(struct device *dev)
+{
+ struct platform_device *pdev;
+ struct omap_device *od;
+ struct omap_hwmod *oh;
+
+ if (!dev)
+ goto save_ctx;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ od = container_of(pdev, struct omap_device, pdev);
+ oh = od->hwmods[0];
+
+ if (!oh || !cpu_is_omap44xx())
+ goto save_ctx;
+
+ if (oh->prcm.omap4.context_reg) {
+ u32 context_reg_val = 0;
+
+ /*Read what context was lost.*/
+ context_reg_val = __raw_readl(oh->prcm.omap4.context_reg);
+
+ /*clear context lost bits after read*/
+ __raw_writel(context_reg_val, oh->prcm.omap4.context_reg);
+
+ /* ABE special case, only report ctx lost when we loose
+ * mem, otherwise, constant firmware reload causes problems.
+ */
+ if (oh->prcm.omap4.context_reg == OMAP4430_RM_ABE_AESS_CONTEXT)
+ context_reg_val &= (1 << 8);
+
+ return (context_reg_val != 0);
+ }
+
+save_ctx:
+ /* by default return true so that driver will restore context*/
+ return true;
+}
+
+/* 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 b0471bb2..0000000
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ /dev/null
@@ -1,363 +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 u32 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
-
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- u32 count;
-
- if (WARN_ON(!dev))
- return 0;
-
- 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));
- if (off_mode_enabled)
- dummy_context_loss_counter++;
- count = dummy_context_loss_counter;
- }
-
- pr_debug("OMAP PM: context loss count for dev %s = %d\n",
- dev_name(dev), count);
-
- return count;
-}
-
-#else
-
-u32 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 49fc0df..92b4496 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -146,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,
@@ -214,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,
@@ -311,7 +311,7 @@ static void _add_optional_clock_clkdev(struct omap_device *od,
* return the context loss counter for that hwmod, otherwise return
* zero.
*/
-u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+int omap_device_get_context_loss_count(struct platform_device *pdev)
{
struct omap_device *od;
u32 ret = 0;
diff --git a/arch/arm/plat-omap/omap_rpmsg.c b/arch/arm/plat-omap/omap_rpmsg.c
new file mode 100644
index 0000000..c0257be
--- /dev/null
+++ b/arch/arm/plat-omap/omap_rpmsg.c
@@ -0,0 +1,601 @@
+/*
+ * 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/remoteproc.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 notifier_block rproc_nb;
+ struct work_struct reset_work;
+ bool slave_reset;
+ struct omap_rpmsg_vproc *slave_next;
+ 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)
+static void rpmsg_reset_work(struct work_struct *work);
+
+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);
+ rproc_last_busy(rpvq->rpdev->rproc);
+ /* 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);
+ rproc_error_notify(rpdev->rproc);
+ 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 void rpmsg_reset_devices(struct omap_rpmsg_vproc *rpdev)
+{
+ /* wait until previous reset requests have finished */
+ flush_work_sync(&rpdev->reset_work);
+ schedule_work(&rpdev->reset_work);
+}
+
+static int rpmsg_rproc_error(struct omap_rpmsg_vproc *rpdev)
+{
+ pr_err("Fatal error in %s\n", rpdev->rproc_name);
+#ifdef CONFIG_OMAP_RPMSG_RECOVERY
+ if (rpdev->slave_reset)
+ return NOTIFY_DONE;
+ rpmsg_reset_devices(rpdev);
+#endif
+
+ return NOTIFY_DONE;
+}
+
+static int rpmsg_rproc_suspend(struct omap_rpmsg_vproc *rpdev)
+{
+ if (virtqueue_more_used(rpdev->vq[0]))
+ return NOTIFY_BAD;
+ return NOTIFY_DONE;
+}
+
+static int rpmsg_rproc_pos_suspend(struct omap_rpmsg_vproc *rpdev)
+{
+ if (rpdev->mbox) {
+ omap_mbox_put(rpdev->mbox, &rpdev->nb);
+ rpdev->mbox = NULL;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int rpmsg_rproc_resume(struct omap_rpmsg_vproc *rpdev)
+{
+ if (!rpdev->mbox)
+ rpdev->mbox = omap_mbox_get(rpdev->mbox_name, &rpdev->nb);
+
+ return NOTIFY_DONE;
+}
+
+static int rpmsg_rproc_secure(struct omap_rpmsg_vproc *rpdev, bool s)
+{
+ pr_err("%s: %s secure mode\n", rpdev->rproc_name, s ? "enter" : "exit");
+ if (rpdev->slave_reset)
+ return NOTIFY_DONE;
+ rpmsg_reset_devices(rpdev);
+
+ return NOTIFY_DONE;
+}
+
+static int rpmsg_rproc_events(struct notifier_block *this,
+ unsigned long type, void *data)
+{
+ struct omap_rpmsg_vproc *rpdev = container_of(this,
+ struct omap_rpmsg_vproc, rproc_nb);
+
+ switch (type) {
+ case RPROC_ERROR:
+ return rpmsg_rproc_error(rpdev);
+ case RPROC_PRE_SUSPEND:
+ return rpmsg_rproc_suspend(rpdev);
+ case RPROC_POS_SUSPEND:
+ return rpmsg_rproc_pos_suspend(rpdev);
+ case RPROC_RESUME:
+ return rpmsg_rproc_resume(rpdev);
+ case RPROC_SECURE:
+ return rpmsg_rproc_secure(rpdev, !!data);
+ }
+ 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);
+
+ rproc_event_unregister(rpdev->rproc, &rpdev->rproc_nb);
+
+ list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
+ struct omap_rpmsg_vq_info *rpvq = vq->priv;
+ iounmap(rpvq->addr);
+ vring_del_virtqueue(vq);
+ kfree(rpvq);
+ }
+
+ if (rpdev->mbox)
+ omap_mbox_put(rpdev->mbox, &rpdev->nb);
+
+ if (rpdev->rproc)
+ rproc_put(rpdev->rproc);
+
+ iounmap(rpdev->buf_mapped);
+}
+
+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;
+ goto put_mbox;
+ }
+ /* register for remoteproc events */
+ rpdev->rproc_nb.notifier_call = rpmsg_rproc_events;
+ rproc_event_register(rpdev->rproc, &rpdev->rproc_nb);
+
+ 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 void rpmsg_reset_work(struct work_struct *work)
+{
+ struct omap_rpmsg_vproc *rpdev =
+ container_of(work, struct omap_rpmsg_vproc, reset_work);
+ struct omap_rpmsg_vproc *tmp;
+ int ret;
+
+ for (tmp = rpdev; tmp; tmp = tmp->slave_next) {
+ pr_err("reseting virtio device %d\n", tmp->vdev.index);
+ unregister_virtio_device(&tmp->vdev);
+ }
+ for (tmp = rpdev; tmp; tmp = tmp->slave_next) {
+ memset(&tmp->vdev.dev, 0, sizeof(struct device));
+ tmp->vdev.dev.release = omap_rpmsg_vproc_release;
+ ret = register_virtio_device(&tmp->vdev);
+ if (ret)
+ pr_err("error creating virtio device %d\n", ret);
+ }
+}
+
+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,
+ .slave_next = &omap_rpmsg_vprocs[1],
+ },
+ /* 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,
+ .slave_reset = true,
+ },
+};
+
+static int __init omap_rpmsg_ini(void)
+{
+ int i, ret = 0;
+ phys_addr_t paddr = omap_ipu_get_mempool_base(
+ OMAP_RPROC_MEMPOOL_STATIC);
+ phys_addr_t psize = omap_ipu_get_mempool_size(
+ OMAP_RPROC_MEMPOOL_STATIC);
+
+ 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;
+ }
+
+ /*
+ * vring buffers are expected to be present at the beginning
+ * of the chosen remoteproc pool
+ */
+ 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;
+ INIT_WORK(&rpdev->reset_work, rpmsg_reset_work);
+
+ 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/rproc_user.c b/arch/arm/plat-omap/rproc_user.c
new file mode 100644
index 0000000..083e4ae
--- /dev/null
+++ b/arch/arm/plat-omap/rproc_user.c
@@ -0,0 +1,185 @@
+/*
+ * Secure Mode Input interface to remoteproc driver
+ *
+ * Copyright (C) 2011 Texas Instruments. All rights reserved.
+ *
+ * Authors: Suman Anna <s-anna@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.
+ *
+ * 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
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <linux/remoteproc.h>
+
+
+#define RPROC_USER_NAME "rproc_user"
+#define RPROC_USER_DEVICES 1
+
+static DEFINE_MUTEX(rproc_user_mutex);
+
+struct rproc_user_device {
+ struct miscdevice mdev;
+};
+
+static struct rproc_user_device *ipu_device;
+static char *rproc_user_name = RPROC_USER_NAME;
+static unsigned secure_cnt;
+
+static int rproc_user_open(struct inode *inode, struct file *filp)
+{
+ filp->private_data = NULL;
+ return 0;
+}
+
+static int rproc_user_release(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+
+ if (filp->private_data) {
+ mutex_lock(&rproc_user_mutex);
+ if (!--secure_cnt)
+ ret = rproc_set_secure("ipu", false);
+ mutex_unlock(&rproc_user_mutex);
+ if (ret)
+ pr_err("rproc normal start failed 0x%x, urghh!!", ret);
+ }
+ return ret;
+}
+
+static ssize_t rproc_user_read(struct file *filp, char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ u8 enable;
+ int ret = 1;
+
+ if (len != 1)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&rproc_user_mutex))
+ return -EINTR;
+ enable = secure_cnt ? 1 : 0;
+ if (copy_to_user((void *)ubuf, &enable, sizeof(enable)))
+ ret = -EFAULT;
+ mutex_unlock(&rproc_user_mutex);
+
+ return ret;
+}
+
+static ssize_t rproc_user_write(struct file *filp, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ int ret = 0;
+ u8 enable;
+
+ if (len != 1)
+ return -EINVAL;
+
+ if (copy_from_user(&enable, (char __user *) ubuf, sizeof(enable)))
+ return -EFAULT;
+
+ if (mutex_lock_interruptible(&rproc_user_mutex))
+ return -EINTR;
+
+ enable = enable ? 1 : 0;
+ if (enable == (int)filp->private_data) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ switch (enable) {
+ case 1:
+ if (!secure_cnt++)
+ ret = rproc_set_secure("ipu", true);
+ if (!ret) {
+ filp->private_data = (void *)1;
+ goto out;
+ }
+ /* fall through in case of failure */
+ pr_err("rproc secure start failed, 0x%x\n", ret);
+ case 0:
+ if (!--secure_cnt)
+ ret = rproc_set_secure("ipu", false);
+ if (ret)
+ pr_err("rproc normal start failed 0x%x, urghh!!", ret);
+ else
+ filp->private_data = (void *)0;
+ }
+ if (enable != (int)filp->private_data)
+ ret = -EACCES;
+out:
+ mutex_unlock(&rproc_user_mutex);
+
+ return ret ? ret : 1;
+}
+
+static const struct file_operations rproc_user_fops = {
+ .owner = THIS_MODULE,
+ .open = rproc_user_open,
+ .release = rproc_user_release,
+ .read = rproc_user_read,
+ .write = rproc_user_write,
+};
+
+static int __init rproc_user_init(void)
+{
+ int ret;
+
+ ipu_device = kzalloc(sizeof(struct rproc_user_device), GFP_KERNEL);
+ if (!ipu_device) {
+ pr_err("%s: memory allocation failed for ipu_device\n",
+ __func__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ipu_device->mdev.minor = MISC_DYNAMIC_MINOR;
+ ipu_device->mdev.name = rproc_user_name;
+ ipu_device->mdev.fops = &rproc_user_fops;
+ ipu_device->mdev.parent = NULL;
+ ret = misc_register(&ipu_device->mdev);
+ if (ret) {
+ pr_err("rproc_user_init: failed to register rproc_user misc "
+ "device\n");
+ goto misc_fail;
+ }
+ return ret;
+
+misc_fail:
+ kfree(ipu_device);
+exit:
+ return ret;
+}
+module_init(rproc_user_init);
+
+static void __exit rproc_user_exit(void)
+{
+ misc_deregister(&ipu_device->mdev);
+ kfree(ipu_device);
+}
+module_exit(rproc_user_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("RemoteProc Secure Mode Interface Driver");
+MODULE_AUTHOR("Suman Anna");
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 6af3d0b..da97e1f 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -48,9 +48,14 @@
#define OMAP3_SRAM_VA 0xfe400000
#define OMAP3_SRAM_PUB_PA (OMAP3_SRAM_PA + 0x8000)
#define OMAP3_SRAM_PUB_VA (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_VA 0xfe400000
-#define OMAP4_SRAM_PUB_PA (OMAP4_SRAM_PA + 0x4000)
-#define OMAP4_SRAM_PUB_VA (OMAP4_SRAM_VA + 0x4000)
+
+#define OMAP4_SRAM_MAX 0xe000 /* 56K */
+#define OMAP4_SRAM_VA 0xfe400000
+
+#define OMAP4_HS_SRAM_SIZE 0x1000 /* 4K */
+#define OMAP4_HS_SRAM_OFFSET (OMAP4_SRAM_MAX - OMAP4_HS_SRAM_SIZE)
+#define OMAP4_SRAM_PUB_PA (OMAP4_SRAM_PA + OMAP4_HS_SRAM_OFFSET)
+#define OMAP4_SRAM_PUB_VA (OMAP4_SRAM_VA + OMAP4_HS_SRAM_OFFSET)
#if defined(CONFIG_ARCH_OMAP2PLUS)
#define SRAM_BOOTLOADER_SZ 0x00
@@ -76,6 +81,12 @@ static unsigned long omap_sram_start;
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
+static unsigned long omap_barrier_base;
+
+unsigned long omap_get_sram_barrier_base(void)
+{
+ return omap_barrier_base;
+}
/*
* Depending on the target RAMFS firewall setup, the public usable amount of
@@ -128,7 +139,7 @@ static void __init omap_detect_sram(void)
} else if (cpu_is_omap44xx()) {
omap_sram_base = OMAP4_SRAM_PUB_VA;
omap_sram_start = OMAP4_SRAM_PUB_PA;
- omap_sram_size = 0xa000; /* 40K */
+ omap_sram_size = OMAP4_HS_SRAM_SIZE;
} else {
omap_sram_base = OMAP2_SRAM_PUB_VA;
omap_sram_start = OMAP2_SRAM_PUB_PA;
@@ -185,24 +196,25 @@ static void __init omap_detect_sram(void)
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
-static struct map_desc omap_sram_io_desc[] __initdata = {
- { /* .length gets filled in at runtime */
- .virtual = OMAP1_SRAM_VA,
- .pfn = __phys_to_pfn(OMAP1_SRAM_PA),
- .type = MT_MEMORY
- }
-};
-
/*
* Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
*/
static void __init omap_map_sram(void)
{
unsigned long base;
+ struct map_desc omap_sram_io_desc[2];
+ int nr_desc = 1;
if (omap_sram_size == 0)
return;
+ omap_sram_io_desc[0].virtual = omap_sram_base;
+ base = omap_sram_start;
+ base = ROUND_DOWN(base, PAGE_SIZE);
+ omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
+ omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
+ omap_sram_io_desc[0].type = MT_MEMORY;
+
if (cpu_is_omap34xx()) {
/*
* SRAM must be marked as non-cached on OMAP3 since the
@@ -212,14 +224,33 @@ static void __init omap_map_sram(void)
* which will cause the system to hang.
*/
omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
+ } else if (cpu_is_omap44xx()) {
+ /*
+ * Map a page of SRAM with strongly ordered attributes
+ * for interconnect barrier usage.
+ * if we have space, then use a new page, else remap
+ * first map
+ */
+ if (omap_sram_size <= PAGE_SIZE) {
+ omap_sram_io_desc[0].type = MT_MEMORY_SO;
+ omap_barrier_base = omap_sram_io_desc[0].virtual;
+ } else {
+ omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size
+ - PAGE_SIZE, PAGE_SIZE);
+ omap_sram_io_desc[1].virtual =
+ omap_sram_base + omap_sram_io_desc[0].length;
+ omap_barrier_base = omap_sram_io_desc[1].virtual;
+ base = omap_sram_start + omap_sram_io_desc[0].length;
+ base = ROUND_DOWN(base, PAGE_SIZE);
+ omap_sram_io_desc[1].pfn = __phys_to_pfn(base);
+ omap_sram_io_desc[1].length = PAGE_SIZE;
+ omap_sram_io_desc[1].type = MT_MEMORY_SO;
+ nr_desc = 2;
+ }
}
- omap_sram_io_desc[0].virtual = omap_sram_base;
- base = omap_sram_start;
- base = ROUND_DOWN(base, PAGE_SIZE);
- omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
- 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));
+
+ iotable_init(omap_sram_io_desc, nr_desc);
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),
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 192e9dd..fec4bf8 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/cpu.h>
+#include <linux/cpu_pm.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/signal.h>
@@ -403,9 +404,7 @@ static void vfp_enable(void *unused)
set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
}
-#ifdef CONFIG_PM
-#include <linux/syscore_ops.h>
-
+#ifdef CONFIG_CPU_PM
static int vfp_pm_suspend(void)
{
struct thread_info *ti = current_thread_info();
@@ -441,19 +440,33 @@ static void vfp_pm_resume(void)
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
}
-static struct syscore_ops vfp_pm_syscore_ops = {
- .suspend = vfp_pm_suspend,
- .resume = vfp_pm_resume,
+static int vfp_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_PM_ENTER:
+ vfp_pm_suspend();
+ break;
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ vfp_pm_resume();
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block vfp_cpu_pm_notifier_block = {
+ .notifier_call = vfp_cpu_pm_notifier,
};
static void vfp_pm_init(void)
{
- register_syscore_ops(&vfp_pm_syscore_ops);
+ cpu_pm_register_notifier(&vfp_cpu_pm_notifier_block);
}
#else
static inline void vfp_pm_init(void) { }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_CPU_PM */
void vfp_sync_hwstate(struct thread_info *thread)
{